feat:增加eslint+prettier 代码校验格式化

This commit is contained in:
zouzhibing 2022-08-05 16:04:07 +08:00
parent 759763c875
commit efa0fcab52
160 changed files with 16291 additions and 12362 deletions

15
.eslintignore Normal file
View File

@ -0,0 +1,15 @@
*.sh
node_modules
*.md
*.woff
*.ttf
.vscode
.idea
dist
/public
/docs
.husky
.local
/bin
Dockerfile

25
.eslintrc.cjs Normal file
View File

@ -0,0 +1,25 @@
module.exports = {
"env": {
"browser": true,
"es2021": true,
"node":true
},
"extends": [
"eslint:recommended",
"plugin:vue/vue3-essential",
"plugin:@typescript-eslint/recommended",
'plugin:prettier/recommended'
],
"parser": "vue-eslint-parser",
"parserOptions": {
"ecmaVersion": "latest",
"parser": "@typescript-eslint/parser",
"sourceType": "module"
},
"plugins": [
"vue",
"@typescript-eslint"
],
"rules": {
}
}

9
.prettierignore Normal file
View File

@ -0,0 +1,9 @@
/dist/*
.local
.output.js
/node_modules/**
**/*.svg
**/*.sh
/public/*

View File

@ -7,7 +7,8 @@
"dev": "vite",
"build": "vite build",
"preview": "vite preview",
"lint": "eslint . --ext .vue,.js,.ts,.jsx,.tsx --fix"
"lint": "eslint . --ext .vue,.js,.ts,.jsx,.tsx --fix",
"lint:prettier": "prettier --write \"src/**/*.{js,json,tsx,css,less,scss,vue,html,md}\""
},
"dependencies": {
"@better-scroll/core": "^2.4.2",
@ -47,14 +48,19 @@
"@vitejs/plugin-vue": "^3.0.0",
"dart-sass": "^1.25.0",
"eslint": "^8.21.0",
"eslint-config-prettier": "^8.5.0",
"eslint-plugin-prettier": "^4.2.1",
"eslint-plugin-vue": "^9.3.0",
"fast-glob": "^3.2.11",
"prettier": "^2.7.1",
"typescript": "^4.6.4",
"unplugin-auto-import": "^0.10.3",
"unplugin-vue-components": "^0.21.2",
"unplugin-vue-define-options": "^0.7.3",
"vite": "^3.0.0",
"vite-plugin-compression": "^0.5.1",
"vite-plugin-svg-icons": "^2.0.1",
"vite-plugin-vue-setup-extend": "^0.4.0",
"vue-tsc": "^0.38.4"
}
}

14
prettier.config.cjs Normal file
View File

@ -0,0 +1,14 @@
module.exports = {
// 一行的字符数如果超过会进行换行默认为80
printWidth: 100,
// 行位是否使用分号默认为true
semi: false,
vueIndentScriptAndStyle: true,
// 字符串是否使用单引号默认为false使用双引号
singleQuote: true,
// 是否使用尾逗号,有三个可选值"<none|es5|all>"
trailingComma: 'all',
proseWrap: 'never',
htmlWhitespaceSensitivity: 'strict',
endOfLine: 'auto',
};

View File

@ -3,27 +3,27 @@
</template>
<style lang="scss">
#app {
position: relative;
width: 100%;
height: 100%;
/*background: #f6f8f9;*/
/*background: goldenrod;*/
font-family: Avenir, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
color: #2c3e50;
}
html,body{
height: 100%;
background: #f6f8f9;
}
.el-pager li:focus{
border: none;
}
*{
margin: 0;
padding: 0;
}
#app {
position: relative;
width: 100%;
height: 100%;
/*background: #f6f8f9;*/
/*background: goldenrod;*/
font-family: Avenir, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
color: #2c3e50;
}
html,
body {
height: 100%;
background: #f6f8f9;
}
.el-pager li:focus {
border: none;
}
* {
margin: 0;
padding: 0;
}
</style>

View File

@ -1,155 +1,162 @@
<template>
<div :id="id" :class="className" :style="{height:height,width:width}" />
<div :id="id" :class="className" :style="{ height: height, width: width }" />
</template>
<script lang="ts">
import echarts from 'echarts'
import resize from './mixins/resize'
import echarts from 'echarts'
import resize from './mixins/resize'
export default {
mixins: [resize],
props: {
className: {
type: String,
default: 'chart'
export default {
mixins: [resize],
props: {
className: {
type: String,
default: 'chart',
},
id: {
type: String,
default: 'chart',
},
width: {
type: String,
default: '200px',
},
height: {
type: String,
default: '200px',
},
},
id: {
type: String,
default: 'chart'
},
width: {
type: String,
default: '200px'
},
height: {
type: String,
default: '200px'
}
},
data() {
return {
chart: null
}
},
mounted() {
this.initChart()
},
beforeDestroy() {
if (!this.chart) {
return
}
this.chart.dispose()
this.chart = null
},
methods: {
initChart() {
this.chart = echarts.init(document.getElementById(this.id))
const xAxisData = []
const data = []
const data2 = []
for (let i = 0; i < 50; i++) {
xAxisData.push(i)
data.push((Math.sin(i / 5) * (i / 5 - 10) + i / 6) * 5)
data2.push((Math.sin(i / 5) * (i / 5 + 10) + i / 6) * 3)
data() {
return {
chart: null,
}
this.chart.setOption({
backgroundColor: '#08263a',
grid: {
left: '5%',
right: '5%'
},
xAxis: [{
show: false,
data: xAxisData
}, {
show: false,
data: xAxisData
}],
visualMap: {
show: false,
min: 0,
max: 50,
dimension: 0,
inRange: {
color: ['#4a657a', '#308e92', '#b1cfa5', '#f5d69f', '#f5898b', '#ef5055']
}
},
yAxis: {
axisLine: {
show: false
},
axisLabel: {
textStyle: {
color: '#4a657a'
}
},
splitLine: {
show: true,
lineStyle: {
color: '#08263f'
}
},
axisTick: {
show: false
}
},
series: [{
name: 'back',
type: 'bar',
data: data2,
z: 1,
itemStyle: {
normal: {
opacity: 0.4,
barBorderRadius: 5,
shadowBlur: 3,
shadowColor: '#111'
}
}
}, {
name: 'Simulate Shadow',
type: 'line',
data,
z: 2,
showSymbol: false,
animationDelay: 0,
animationEasing: 'linear',
animationDuration: 1200,
lineStyle: {
normal: {
color: 'transparent'
}
},
areaStyle: {
normal: {
color: '#08263a',
shadowBlur: 50,
shadowColor: '#000'
}
}
}, {
name: 'front',
type: 'bar',
data,
xAxisIndex: 1,
z: 3,
itemStyle: {
normal: {
barBorderRadius: 5
}
}
}],
animationEasing: 'elasticOut',
animationEasingUpdate: 'elasticOut',
animationDelay(idx) {
return idx * 20
},
animationDelayUpdate(idx) {
return idx * 20
},
mounted() {
this.initChart()
},
beforeDestroy() {
if (!this.chart) {
return
}
this.chart.dispose()
this.chart = null
},
methods: {
initChart() {
this.chart = echarts.init(document.getElementById(this.id))
const xAxisData = []
const data = []
const data2 = []
for (let i = 0; i < 50; i++) {
xAxisData.push(i)
data.push((Math.sin(i / 5) * (i / 5 - 10) + i / 6) * 5)
data2.push((Math.sin(i / 5) * (i / 5 + 10) + i / 6) * 3)
}
})
}
this.chart.setOption({
backgroundColor: '#08263a',
grid: {
left: '5%',
right: '5%',
},
xAxis: [
{
show: false,
data: xAxisData,
},
{
show: false,
data: xAxisData,
},
],
visualMap: {
show: false,
min: 0,
max: 50,
dimension: 0,
inRange: {
color: ['#4a657a', '#308e92', '#b1cfa5', '#f5d69f', '#f5898b', '#ef5055'],
},
},
yAxis: {
axisLine: {
show: false,
},
axisLabel: {
textStyle: {
color: '#4a657a',
},
},
splitLine: {
show: true,
lineStyle: {
color: '#08263f',
},
},
axisTick: {
show: false,
},
},
series: [
{
name: 'back',
type: 'bar',
data: data2,
z: 1,
itemStyle: {
normal: {
opacity: 0.4,
barBorderRadius: 5,
shadowBlur: 3,
shadowColor: '#111',
},
},
},
{
name: 'Simulate Shadow',
type: 'line',
data,
z: 2,
showSymbol: false,
animationDelay: 0,
animationEasing: 'linear',
animationDuration: 1200,
lineStyle: {
normal: {
color: 'transparent',
},
},
areaStyle: {
normal: {
color: '#08263a',
shadowBlur: 50,
shadowColor: '#000',
},
},
},
{
name: 'front',
type: 'bar',
data,
xAxisIndex: 1,
z: 3,
itemStyle: {
normal: {
barBorderRadius: 5,
},
},
},
],
animationEasing: 'elasticOut',
animationEasingUpdate: 'elasticOut',
animationDelay(idx) {
return idx * 20
},
animationDelayUpdate(idx) {
return idx * 20
},
})
},
},
}
}
</script>

View File

@ -1,230 +1,277 @@
<template>
<div :id="id" :class="className" :style="{height:height,width:width}" />
<div :id="id" :class="className" :style="{ height: height, width: width }" />
</template>
<script lang="ts" setup>
import * as echarts from 'echarts'
import {computed, nextTick, onMounted, ref, watch} from "vue";
import {EChartsType} from "echarts/core";
import {useStore} from "vuex";
// setupstore
const store = useStore()
let props = defineProps({
import * as echarts from 'echarts'
import { computed, nextTick, onMounted, ref, watch } from 'vue'
import { EChartsType } from 'echarts/core'
import { useStore } from 'vuex'
// setupstore
const store = useStore()
let props = defineProps({
className: {
type: String,
default: 'chart'
default: 'chart',
},
id: {
type: String,
default: 'chart'
default: 'chart',
},
width: {
type: String,
default: '200px'
default: '200px',
},
height: {
type: String,
default: '200px'
}
})
const isCollapse = computed(()=>{
return store.state.app.isCollapse
})
default: '200px',
},
})
const isCollapse = computed(() => {
return store.state.app.isCollapse
})
let chart:EChartsType;
let chart: EChartsType
const initChart =()=> {
let chart = echarts.init(document.getElementById(props.id))
chart.setOption({
backgroundColor: '#394056',
title: {
top: 20,
text: 'Requests',
textStyle: {
fontWeight: 'normal',
fontSize: 16,
color: '#F1F1F3'
},
left: '1%'
},
tooltip: {
trigger: 'axis',
axisPointer: {
lineStyle: {
color: '#57617B'
}
}
},
legend: {
top: 20,
icon: 'rect',
itemWidth: 14,
itemHeight: 5,
itemGap: 13,
data: ['CMCC', 'CTCC', 'CUCC'],
right: '4%',
textStyle: {
fontSize: 12,
color: '#F1F1F3'
}
},
grid: {
top: 100,
left: '2%',
right: '2%',
bottom: '2%',
containLabel: true
},
xAxis: [{
type: 'category',
boundaryGap: false,
axisLine: {
lineStyle: {
color: '#57617B'
}
},
data: ['13:00', '13:05', '13:10', '13:15', '13:20', '13:25', '13:30', '13:35', '13:40', '13:45', '13:50', '13:55']
}],
yAxis: [{
type: 'value',
name: '(%)',
axisTick: {
show: false
},
axisLine: {
lineStyle: {
color: '#57617B'
}
},
axisLabel: {
margin: 10,
const initChart = () => {
let chart = echarts.init(document.getElementById(props.id))
chart.setOption({
backgroundColor: '#394056',
title: {
top: 20,
text: 'Requests',
textStyle: {
fontSize: 14
}
fontWeight: 'normal',
fontSize: 16,
color: '#F1F1F3',
},
left: '1%',
},
splitLine: {
lineStyle: {
color: '#57617B'
}
}
}],
series: [{
name: 'CMCC',
type: 'line',
smooth: true,
symbol: 'circle',
symbolSize: 5,
showSymbol: false,
lineStyle: {
normal: {
width: 1
}
tooltip: {
trigger: 'axis',
axisPointer: {
lineStyle: {
color: '#57617B',
},
},
},
areaStyle: {
normal: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
offset: 0,
color: 'rgba(137, 189, 27, 0.3)'
}, {
offset: 0.8,
color: 'rgba(137, 189, 27, 0)'
}], false),
shadowColor: 'rgba(0, 0, 0, 0.1)',
shadowBlur: 10
}
legend: {
top: 20,
icon: 'rect',
itemWidth: 14,
itemHeight: 5,
itemGap: 13,
data: ['CMCC', 'CTCC', 'CUCC'],
right: '4%',
textStyle: {
fontSize: 12,
color: '#F1F1F3',
},
},
itemStyle: {
normal: {
color: 'rgb(137,189,27)',
borderColor: 'rgba(137,189,2,0.27)',
borderWidth: 12
grid: {
top: 100,
left: '2%',
right: '2%',
bottom: '2%',
containLabel: true,
},
xAxis: [
{
type: 'category',
boundaryGap: false,
axisLine: {
lineStyle: {
color: '#57617B',
},
},
data: [
'13:00',
'13:05',
'13:10',
'13:15',
'13:20',
'13:25',
'13:30',
'13:35',
'13:40',
'13:45',
'13:50',
'13:55',
],
},
],
yAxis: [
{
type: 'value',
name: '(%)',
axisTick: {
show: false,
},
axisLine: {
lineStyle: {
color: '#57617B',
},
},
axisLabel: {
margin: 10,
textStyle: {
fontSize: 14,
},
},
splitLine: {
lineStyle: {
color: '#57617B',
},
},
},
],
series: [
{
name: 'CMCC',
type: 'line',
smooth: true,
symbol: 'circle',
symbolSize: 5,
showSymbol: false,
lineStyle: {
normal: {
width: 1,
},
},
areaStyle: {
normal: {
color: new echarts.graphic.LinearGradient(
0,
0,
0,
1,
[
{
offset: 0,
color: 'rgba(137, 189, 27, 0.3)',
},
{
offset: 0.8,
color: 'rgba(137, 189, 27, 0)',
},
],
false,
),
shadowColor: 'rgba(0, 0, 0, 0.1)',
shadowBlur: 10,
},
},
itemStyle: {
normal: {
color: 'rgb(137,189,27)',
borderColor: 'rgba(137,189,2,0.27)',
borderWidth: 12,
},
},
data: [220, 182, 191, 134, 150, 120, 110, 125, 145, 122, 165, 122],
},
{
name: 'CTCC',
type: 'line',
smooth: true,
symbol: 'circle',
symbolSize: 5,
showSymbol: false,
lineStyle: {
normal: {
width: 1,
},
},
areaStyle: {
normal: {
color: new echarts.graphic.LinearGradient(
0,
0,
0,
1,
[
{
offset: 0,
color: 'rgba(0, 136, 212, 0.3)',
},
{
offset: 0.8,
color: 'rgba(0, 136, 212, 0)',
},
],
false,
),
shadowColor: 'rgba(0, 0, 0, 0.1)',
shadowBlur: 10,
},
},
itemStyle: {
normal: {
color: 'rgb(0,136,212)',
borderColor: 'rgba(0,136,212,0.2)',
borderWidth: 12,
},
},
data: [120, 110, 125, 145, 122, 165, 122, 220, 182, 191, 134, 150],
},
{
name: 'CUCC',
type: 'line',
smooth: true,
symbol: 'circle',
symbolSize: 5,
showSymbol: false,
lineStyle: {
normal: {
width: 1,
},
},
areaStyle: {
normal: {
color: new echarts.graphic.LinearGradient(
0,
0,
0,
1,
[
{
offset: 0,
color: 'rgba(219, 50, 51, 0.3)',
},
{
offset: 0.8,
color: 'rgba(219, 50, 51, 0)',
},
],
false,
),
shadowColor: 'rgba(0, 0, 0, 0.1)',
shadowBlur: 10,
},
},
itemStyle: {
normal: {
color: 'rgb(219,50,51)',
borderColor: 'rgba(219,50,51,0.2)',
borderWidth: 12,
},
},
data: [220, 182, 125, 145, 122, 191, 134, 150, 120, 110, 165, 122],
},
],
})
return chart
}
}
},
data: [220, 182, 191, 134, 150, 120, 110, 125, 145, 122, 165, 122]
}, {
name: 'CTCC',
type: 'line',
smooth: true,
symbol: 'circle',
symbolSize: 5,
showSymbol: false,
lineStyle: {
normal: {
width: 1
}
},
areaStyle: {
normal: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
offset: 0,
color: 'rgba(0, 136, 212, 0.3)'
}, {
offset: 0.8,
color: 'rgba(0, 136, 212, 0)'
}], false),
shadowColor: 'rgba(0, 0, 0, 0.1)',
shadowBlur: 10
}
},
itemStyle: {
normal: {
color: 'rgb(0,136,212)',
borderColor: 'rgba(0,136,212,0.2)',
borderWidth: 12
}
},
data: [120, 110, 125, 145, 122, 165, 122, 220, 182, 191, 134, 150]
}, {
name: 'CUCC',
type: 'line',
smooth: true,
symbol: 'circle',
symbolSize: 5,
showSymbol: false,
lineStyle: {
normal: {
width: 1
}
},
areaStyle: {
normal: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
offset: 0,
color: 'rgba(219, 50, 51, 0.3)'
}, {
offset: 0.8,
color: 'rgba(219, 50, 51, 0)'
}], false),
shadowColor: 'rgba(0, 0, 0, 0.1)',
shadowBlur: 10
}
},
itemStyle: {
normal: {
color: 'rgb(219,50,51)',
borderColor: 'rgba(219,50,51,0.2)',
borderWidth: 12
}
},
data: [220, 182, 125, 145, 122, 191, 134, 150, 120, 110, 165, 122]
}]
})
return chart
}
watch(isCollapse,()=>{
setTimeout(()=>{
chart&&chart.resize()
},300)
})
onMounted(()=>{
chart = initChart()
window.addEventListener('resize',function (){
chart&&chart.resize()
watch(isCollapse, () => {
setTimeout(() => {
chart && chart.resize()
}, 300)
})
})
onMounted(() => {
chart = initChart()
window.addEventListener('resize', function () {
chart && chart.resize()
})
})
</script>

View File

@ -1,271 +1,238 @@
<template>
<div :id="id" :class="className" :style="{height:height,width:width}" />
<div :id="id" :class="className" :style="{ height: height, width: width }" />
</template>
<script lang="ts">
import echarts from 'echarts'
import resize from './mixins/resize'
import echarts from 'echarts'
import resize from './mixins/resize'
export default {
mixins: [resize],
props: {
className: {
type: String,
default: 'chart'
export default {
mixins: [resize],
props: {
className: {
type: String,
default: 'chart',
},
id: {
type: String,
default: 'chart',
},
width: {
type: String,
default: '200px',
},
height: {
type: String,
default: '200px',
},
},
id: {
type: String,
default: 'chart'
data() {
return {
chart: null,
}
},
width: {
type: String,
default: '200px'
mounted() {
this.initChart()
},
height: {
type: String,
default: '200px'
}
},
data() {
return {
chart: null
}
},
mounted() {
this.initChart()
},
beforeDestroy() {
if (!this.chart) {
return
}
this.chart.dispose()
this.chart = null
},
methods: {
initChart() {
this.chart = echarts.init(document.getElementById(this.id))
const xData = (function() {
const data = []
for (let i = 1; i < 13; i++) {
data.push(i + 'month')
}
return data
}())
this.chart.setOption({
backgroundColor: '#344b58',
title: {
text: 'statistics',
x: '20',
top: '20',
textStyle: {
color: '#fff',
fontSize: '22'
},
subtextStyle: {
color: '#90979c',
fontSize: '16'
beforeDestroy() {
if (!this.chart) {
return
}
this.chart.dispose()
this.chart = null
},
methods: {
initChart() {
this.chart = echarts.init(document.getElementById(this.id))
const xData = (function () {
const data = []
for (let i = 1; i < 13; i++) {
data.push(i + 'month')
}
},
tooltip: {
trigger: 'axis',
axisPointer: {
return data
})()
this.chart.setOption({
backgroundColor: '#344b58',
title: {
text: 'statistics',
x: '20',
top: '20',
textStyle: {
color: '#fff'
}
}
},
grid: {
left: '5%',
right: '5%',
borderWidth: 0,
top: 150,
bottom: 95,
textStyle: {
color: '#fff'
}
},
legend: {
x: '5%',
top: '10%',
textStyle: {
color: '#90979c'
color: '#fff',
fontSize: '22',
},
subtextStyle: {
color: '#90979c',
fontSize: '16',
},
},
data: ['female', 'male', 'average']
},
calculable: true,
xAxis: [{
type: 'category',
axisLine: {
lineStyle: {
color: '#90979c'
}
tooltip: {
trigger: 'axis',
axisPointer: {
textStyle: {
color: '#fff',
},
},
},
splitLine: {
show: false
grid: {
left: '5%',
right: '5%',
borderWidth: 0,
top: 150,
bottom: 95,
textStyle: {
color: '#fff',
},
},
axisTick: {
show: false
legend: {
x: '5%',
top: '10%',
textStyle: {
color: '#90979c',
},
data: ['female', 'male', 'average'],
},
splitArea: {
show: false
},
axisLabel: {
interval: 0
},
data: xData
}],
yAxis: [{
type: 'value',
splitLine: {
show: false
},
axisLine: {
lineStyle: {
color: '#90979c'
}
},
axisTick: {
show: false
},
axisLabel: {
interval: 0
},
splitArea: {
show: false
}
}],
dataZoom: [{
show: true,
height: 30,
xAxisIndex: [
0
],
bottom: 30,
start: 10,
end: 80,
handleIcon: 'path://M306.1,413c0,2.2-1.8,4-4,4h-59.8c-2.2,0-4-1.8-4-4V200.8c0-2.2,1.8-4,4-4h59.8c2.2,0,4,1.8,4,4V413z',
handleSize: '110%',
handleStyle: {
color: '#d3dee5'
},
textStyle: {
color: '#fff' },
borderColor: '#90979c'
}, {
type: 'inside',
show: true,
height: 15,
start: 1,
end: 35
}],
series: [{
name: 'female',
type: 'bar',
stack: 'total',
barMaxWidth: 35,
barGap: '10%',
itemStyle: {
normal: {
color: 'rgba(255,144,128,1)',
label: {
show: true,
textStyle: {
color: '#fff'
calculable: true,
xAxis: [
{
type: 'category',
axisLine: {
lineStyle: {
color: '#90979c',
},
position: 'insideTop',
formatter(p) {
return p.value > 0 ? p.value : ''
}
}
}
},
data: [
709,
1917,
2455,
2610,
1719,
1433,
1544,
3285,
5208,
3372,
2484,
4078
]
},
},
splitLine: {
show: false,
},
axisTick: {
show: false,
},
splitArea: {
show: false,
},
axisLabel: {
interval: 0,
},
data: xData,
},
],
yAxis: [
{
type: 'value',
splitLine: {
show: false,
},
axisLine: {
lineStyle: {
color: '#90979c',
},
},
axisTick: {
show: false,
},
axisLabel: {
interval: 0,
},
splitArea: {
show: false,
},
},
],
dataZoom: [
{
show: true,
height: 30,
xAxisIndex: [0],
bottom: 30,
start: 10,
end: 80,
handleIcon:
'path://M306.1,413c0,2.2-1.8,4-4,4h-59.8c-2.2,0-4-1.8-4-4V200.8c0-2.2,1.8-4,4-4h59.8c2.2,0,4,1.8,4,4V413z',
handleSize: '110%',
handleStyle: {
color: '#d3dee5',
},
textStyle: {
color: '#fff',
},
borderColor: '#90979c',
},
{
type: 'inside',
show: true,
height: 15,
start: 1,
end: 35,
},
],
series: [
{
name: 'female',
type: 'bar',
stack: 'total',
barMaxWidth: 35,
barGap: '10%',
itemStyle: {
normal: {
color: 'rgba(255,144,128,1)',
label: {
show: true,
textStyle: {
color: '#fff',
},
position: 'insideTop',
formatter(p) {
return p.value > 0 ? p.value : ''
},
},
},
},
data: [709, 1917, 2455, 2610, 1719, 1433, 1544, 3285, 5208, 3372, 2484, 4078],
},
{
name: 'male',
type: 'bar',
stack: 'total',
itemStyle: {
normal: {
color: 'rgba(0,191,183,1)',
barBorderRadius: 0,
label: {
show: true,
position: 'top',
formatter(p) {
return p.value > 0 ? p.value : ''
}
}
}
},
data: [
327,
1776,
507,
1200,
800,
482,
204,
1390,
1001,
951,
381,
220
]
}, {
name: 'average',
type: 'line',
stack: 'total',
symbolSize: 10,
symbol: 'circle',
itemStyle: {
normal: {
color: 'rgba(252,230,48,1)',
barBorderRadius: 0,
label: {
show: true,
position: 'top',
formatter(p) {
return p.value > 0 ? p.value : ''
}
}
}
},
data: [
1036,
3693,
2962,
3810,
2519,
1915,
1748,
4675,
6209,
4323,
2865,
4298
]
}
]
})
}
{
name: 'male',
type: 'bar',
stack: 'total',
itemStyle: {
normal: {
color: 'rgba(0,191,183,1)',
barBorderRadius: 0,
label: {
show: true,
position: 'top',
formatter(p) {
return p.value > 0 ? p.value : ''
},
},
},
},
data: [327, 1776, 507, 1200, 800, 482, 204, 1390, 1001, 951, 381, 220],
},
{
name: 'average',
type: 'line',
stack: 'total',
symbolSize: 10,
symbol: 'circle',
itemStyle: {
normal: {
color: 'rgba(252,230,48,1)',
barBorderRadius: 0,
label: {
show: true,
position: 'top',
formatter(p) {
return p.value > 0 ? p.value : ''
},
},
},
},
data: [1036, 3693, 2962, 3810, 2519, 1915, 1748, 4675, 6209, 4323, 2865, 4298],
},
],
})
},
},
}
}
</script>

View File

@ -4,7 +4,7 @@ export default {
data() {
return {
$_sidebarElm: null,
$_resizeHandler: null
$_resizeHandler: null,
}
},
mounted() {
@ -40,17 +40,19 @@ export default {
window.addEventListener('resize', this.$_resizeHandler)
this.$_sidebarElm = document.getElementsByClassName('sidebar-container')[0]
this.$_sidebarElm && this.$_sidebarElm.addEventListener('transitionend', this.$_sidebarResizeHandler)
this.$_sidebarElm &&
this.$_sidebarElm.addEventListener('transitionend', this.$_sidebarResizeHandler)
},
destroyListener() {
window.removeEventListener('resize', this.$_resizeHandler)
this.$_resizeHandler = null
this.$_sidebarElm && this.$_sidebarElm.removeEventListener('transitionend', this.$_sidebarResizeHandler)
this.$_sidebarElm &&
this.$_sidebarElm.removeEventListener('transitionend', this.$_sidebarResizeHandler)
},
resize() {
const { chart } = this
chart && chart.resize()
}
}
},
},
}

View File

@ -1,9 +1,9 @@
<script setup lang="ts">
import { ref } from 'vue'
import { ref } from 'vue'
defineProps<{ msg: string }>()
defineProps<{ msg: string }>()
const count = ref(0)
const count = ref(0)
</script>
<template>
@ -19,9 +19,8 @@ const count = ref(0)
<p>
Check out
<a href="https://vuejs.org/guide/quick-start.html#local" target="_blank"
>create-vue</a
>, the official Vue + Vite starter
<a href="https://vuejs.org/guide/quick-start.html#local" target="_blank">create-vue</a>, the
official Vue + Vite starter
</p>
<p>
Install
@ -32,7 +31,7 @@ const count = ref(0)
</template>
<style scoped>
.read-the-docs {
color: #888;
}
.read-the-docs {
color: #888;
}
</style>

View File

@ -5,33 +5,32 @@
</template>
<script lang="ts">
import { computed } from "@vue/reactivity";
export default {
name: "baseSvgIcon",
props: {
iconClass: { type: String },
className: { type: String },
},
setup(props) {
console.log(11111111)
const iconName = computed(() => {
return props.iconClass ? `#icon-${props.iconClass}` : "#icon";
});
const svgClass = computed(() => {
return props.className ? "svg-icon " + props.className : "svg-icon";
});
return { iconName, svgClass };
},
};
import { computed } from 'vue'
export default {
name: 'baseSvgIcon',
props: {
iconClass: { type: String },
className: { type: String },
},
setup(props) {
console.log(11111111)
const iconName = computed(() => {
return props.iconClass ? `#icon-${props.iconClass}` : '#icon'
})
const svgClass = computed(() => {
return props.className ? 'svg-icon ' + props.className : 'svg-icon'
})
return { iconName, svgClass }
},
}
</script>
<style scoped lang="scss">
.svg-icon {
width: 1em;
height: 1em;
vertical-align: -0.15em;
fill: currentColor;
overflow: hidden;
}
.svg-icon {
width: 1em;
height: 1em;
vertical-align: -0.15em;
fill: currentColor;
overflow: hidden;
}
</style>

View File

@ -1,8 +1,8 @@
<template>
<div class="zb-pipeline">
<zb-pipeline-start/>
<zb-pipeline-start />
</div>
</template>
<script lang="ts" setup>
import ZbPipelineStart from './zb-pipeline-start'
import ZbPipelineStart from './zb-pipeline-start'
</script>

View File

@ -1,6 +1,10 @@
<template>
<div class="zb-pipeline-start-wrapper">
<div class="zb-pipeline-start" v-bind:class="control === value ? 'active' : ''" v-on:click="handleClick">
<div
class="zb-pipeline-start"
v-bind:class="control === value ? 'active' : ''"
v-on:click="handleClick"
>
<div class="zb-pipeline-start-header">
<zb-icon type="play-filled" />
</div>
@ -8,14 +12,14 @@
<div class="zb-pipeline-start-title">开始</div>
<div class="zb-pipeline-start-tooltip">
<el-tooltip placement="top-start" content="点击进行构建基础设置">
<el-icon >
<el-icon>
<Help />
</el-icon>
</el-tooltip>
<!-- <zb-tooltip placement="right">-->
<!-- <zb-icon type="help" />-->
<!-- <div slot="content">点击进行构建基础设置</div>-->
<!-- </zb-tooltip>-->
<!-- <zb-tooltip placement="right">-->
<!-- <zb-icon type="help" />-->
<!-- <div slot="content">点击进行构建基础设置</div>-->
<!-- </zb-tooltip>-->
</div>
</div>
</div>
@ -23,41 +27,128 @@
</div>
</template>
<script lang="ts" setup>
import {
Help
} from '@element-plus/icons-vue'
import { Help } from '@element-plus/icons-vue'
</script>
<style>
/* zb-pipeline-start-wrapper */
.zb-pipeline-start-wrapper { position:relative; padding:0 40px; }
/* zb-pipeline-start-wrapper */
.zb-pipeline-start-wrapper {
position: relative;
padding: 0 40px;
}
/* zb-pipeline-start */
.zb-pipeline-start { cursor:pointer; user-select:none; position:relative; display:flex; justify-content:flex-start; align-items:stretch; width:200px; height:40px; border-radius:2px; background-color:#fff; }
.zb-pipeline-start:after { content:""; position:absolute; top:20px; right:-40px; display:block; width:40px; height:1px; background-color:#2d8cf0; }
.zb-pipeline-start .zb-pipeline-start-header { display:flex; justify-content:center; align-items:center; width:40px; border-width:1px 0 1px 1px; border-style:solid; border-color:#2d8cf0; border-radius:2px 0 0 2px; background-color:#2d8cf0; color:#fff; font-size:14px; font-weight:600; transition:all 0.2s cubic-bezier(0.23,1,0.32,1); }
.zb-pipeline-start .zb-pipeline-start-body { flex:1; display:flex; border-width:1px 1px 1px 0; border-style:solid; border-color:#e3e8f0; border-radius:0 2px 2px 0; padding:0 8px; overflow:hidden; transition:all 0.2s cubic-bezier(0.23,1,0.32,1); }
.zb-pipeline-start .zb-pipeline-start-title { flex:1; display:block; overflow:hidden; color:#262626; font-size:14px; font-weight:600; line-height:38px; white-space:nowrap; text-overflow:ellipsis; }
.zb-pipeline-start .zb-pipeline-start-tooltip { cursor:pointer; display:flex; justify-content:center; align-items:center; margin-left:8px; }
.zb-pipeline-start .zb-pipeline-start-tooltip .zb-tooltip { display:block; }
.zb-pipeline-start .zb-pipeline-start-tooltip .zb-icon { display:block; color:#595959; font-size:14px; }
/* zb-pipeline-start */
.zb-pipeline-start {
cursor: pointer;
user-select: none;
position: relative;
display: flex;
justify-content: flex-start;
align-items: stretch;
width: 200px;
height: 40px;
border-radius: 2px;
background-color: #fff;
}
.zb-pipeline-start:after {
content: '';
position: absolute;
top: 20px;
right: -40px;
display: block;
width: 40px;
height: 1px;
background-color: #2d8cf0;
}
.zb-pipeline-start .zb-pipeline-start-header {
display: flex;
justify-content: center;
align-items: center;
width: 40px;
border-width: 1px 0 1px 1px;
border-style: solid;
border-color: #2d8cf0;
border-radius: 2px 0 0 2px;
background-color: #2d8cf0;
color: #fff;
font-size: 14px;
font-weight: 600;
transition: all 0.2s cubic-bezier(0.23, 1, 0.32, 1);
}
.zb-pipeline-start .zb-pipeline-start-body {
flex: 1;
display: flex;
border-width: 1px 1px 1px 0;
border-style: solid;
border-color: #e3e8f0;
border-radius: 0 2px 2px 0;
padding: 0 8px;
overflow: hidden;
transition: all 0.2s cubic-bezier(0.23, 1, 0.32, 1);
}
.zb-pipeline-start .zb-pipeline-start-title {
flex: 1;
display: block;
overflow: hidden;
color: #262626;
font-size: 14px;
font-weight: 600;
line-height: 38px;
white-space: nowrap;
text-overflow: ellipsis;
}
.zb-pipeline-start .zb-pipeline-start-tooltip {
cursor: pointer;
display: flex;
justify-content: center;
align-items: center;
margin-left: 8px;
}
.zb-pipeline-start .zb-pipeline-start-tooltip .zb-tooltip {
display: block;
}
.zb-pipeline-start .zb-pipeline-start-tooltip .zb-icon {
display: block;
color: #595959;
font-size: 14px;
}
/* zb-pipeline-start hover */
.zb-pipeline-start:hover { }
.zb-pipeline-start:hover:after { }
.zb-pipeline-start:hover .zb-pipeline-start-header { border-color:#2d8cf0; }
.zb-pipeline-start:hover .zb-pipeline-start-body { border-color:#2d8cf0; }
.zb-pipeline-start:hover .zb-pipeline-start-title { }
.zb-pipeline-start:hover .zb-pipeline-start-tooltip { }
.zb-pipeline-start:hover .zb-pipeline-start-tooltip .zb-tooltip { }
.zb-pipeline-start:hover .zb-pipeline-start-tooltip .zb-icon { }
/* zb-pipeline-start hover */
.zb-pipeline-start:hover {
}
.zb-pipeline-start:hover:after {
}
.zb-pipeline-start:hover .zb-pipeline-start-header {
border-color: #2d8cf0;
}
.zb-pipeline-start:hover .zb-pipeline-start-body {
border-color: #2d8cf0;
}
.zb-pipeline-start:hover .zb-pipeline-start-title {
}
.zb-pipeline-start:hover .zb-pipeline-start-tooltip {
}
.zb-pipeline-start:hover .zb-pipeline-start-tooltip .zb-tooltip {
}
.zb-pipeline-start:hover .zb-pipeline-start-tooltip .zb-icon {
}
/* zb-pipeline-start active */
.zb-pipeline-start.active { }
.zb-pipeline-start.active:after { }
.zb-pipeline-start.active .zb-pipeline-start-header { border-color:#2d8cf0; }
.zb-pipeline-start.active .zb-pipeline-start-body { border-color:#2d8cf0; }
.zb-pipeline-start.active .zb-pipeline-start-title { }
.zb-pipeline-start.active .zb-pipeline-start-tooltip { }
.zb-pipeline-start.active .zb-pipeline-start-tooltip .zb-tooltip { }
.zb-pipeline-start.active .zb-pipeline-start-tooltip .zb-icon { }
/* zb-pipeline-start active */
.zb-pipeline-start.active {
}
.zb-pipeline-start.active:after {
}
.zb-pipeline-start.active .zb-pipeline-start-header {
border-color: #2d8cf0;
}
.zb-pipeline-start.active .zb-pipeline-start-body {
border-color: #2d8cf0;
}
.zb-pipeline-start.active .zb-pipeline-start-title {
}
.zb-pipeline-start.active .zb-pipeline-start-tooltip {
}
.zb-pipeline-start.active .zb-pipeline-start-tooltip .zb-tooltip {
}
.zb-pipeline-start.active .zb-pipeline-start-tooltip .zb-icon {
}
</style>

View File

@ -1,8 +1,12 @@
<template>
<el-breadcrumb class="app-breadcrumb" separator="/">
<transition-group name="breadcrumb">
<el-breadcrumb-item v-for="(item,index) in obj.levelList" :key="item.path">
<span v-if="item.redirect==='noRedirect'||index==obj.levelList.length-1" class="no-redirect">{{ item.meta.title }}</span>
<el-breadcrumb-item v-for="(item, index) in obj.levelList" :key="item.path">
<span
v-if="item.redirect === 'noRedirect' || index == obj.levelList.length - 1"
class="no-redirect"
>{{ item.meta.title }}</span
>
<a v-else @click.prevent="handleLink(item)">{{ item.meta.title }}</a>
</el-breadcrumb-item>
</transition-group>
@ -11,21 +15,23 @@
<script lang="ts" setup>
import pathToRegexp from 'path-to-regexp'
import {onMounted, reactive, watch} from "vue";
import {useRoute} from 'vue-router'
import { onMounted, reactive, watch } from 'vue'
import { useRoute } from 'vue-router'
const obj = reactive({levelList:{}})
const obj = reactive({ levelList: {} })
const route = useRoute()
//
const getBreadcrumb = ()=>{
let matched = route.matched.filter(item => item.meta && item.meta.title)
const getBreadcrumb = () => {
let matched = route.matched.filter((item) => item.meta && item.meta.title)
const first = matched[0]
obj.levelList = matched.filter(item => item.meta && item.meta.title && item.meta.breadcrumb !== false)
obj.levelList = matched.filter(
(item) => item.meta && item.meta.title && item.meta.breadcrumb !== false,
)
}
onMounted(()=>{
onMounted(() => {
getBreadcrumb()
watch(route,()=>{
watch(route, () => {
if (route.path.startsWith('/redirect/')) {
return
}
@ -35,13 +41,13 @@
</script>
<style lang="scss" scoped>
.app-breadcrumb.el-breadcrumb {
margin-left: 10px;
display: inline-block;
font-size: 14px;
margin-bottom: 4px;
.no-redirect {
cursor: text;
.app-breadcrumb.el-breadcrumb {
margin-left: 10px;
display: inline-block;
font-size: 14px;
margin-bottom: 4px;
.no-redirect {
cursor: text;
}
}
}
</style>

View File

@ -6,18 +6,16 @@
</div>
</template>
<script lang="ts" setup>
</script>
<script lang="ts" setup></script>
<style lang="scss" scoped>
.m-container-layout{
.m-container-layout {
//margin: 20px;
padding: 20px;
box-sizing: border-box;
width: 100%;
height: 100%;
.m-container-layout-inner{
.m-container-layout-inner {
background: white;
padding: 20px;
width: 100%;

View File

@ -1,5 +1,5 @@
import CountTo from './vue-countTo.vue';
export default CountTo;
import CountTo from './vue-countTo.vue'
export default CountTo
if (typeof window !== 'undefined' && window.Vue) {
window.Vue.component('count-to', CountTo);
window.Vue.component('count-to', CountTo)
}

View File

@ -6,27 +6,32 @@ let cancelAnimationFrame
const isServer = typeof window === 'undefined'
if (isServer) {
requestAnimationFrame = function() {
requestAnimationFrame = function () {
return
}
cancelAnimationFrame = function() {
cancelAnimationFrame = function () {
return
}
} else {
requestAnimationFrame = window.requestAnimationFrame
cancelAnimationFrame = window.cancelAnimationFrame
let prefix
// 通过遍历各浏览器前缀来得到requestAnimationFrame和cancelAnimationFrame在当前浏览器的实现形式
// 通过遍历各浏览器前缀来得到requestAnimationFrame和cancelAnimationFrame在当前浏览器的实现形式
for (let i = 0; i < prefixes.length; i++) {
if (requestAnimationFrame && cancelAnimationFrame) { break }
if (requestAnimationFrame && cancelAnimationFrame) {
break
}
prefix = prefixes[i]
requestAnimationFrame = requestAnimationFrame || window[prefix + 'RequestAnimationFrame']
cancelAnimationFrame = cancelAnimationFrame || window[prefix + 'CancelAnimationFrame'] || window[prefix + 'CancelRequestAnimationFrame']
cancelAnimationFrame =
cancelAnimationFrame ||
window[prefix + 'CancelAnimationFrame'] ||
window[prefix + 'CancelRequestAnimationFrame']
}
// 如果当前浏览器不支持requestAnimationFrame和cancelAnimationFrame则会退到setTimeout
if (!requestAnimationFrame || !cancelAnimationFrame) {
requestAnimationFrame = function(callback) {
requestAnimationFrame = function (callback) {
const currTime = new Date().getTime()
// 为了使setTimteout的尽可能的接近每秒60帧的效果
const timeToCall = Math.max(0, 16 - (currTime - lastTime))
@ -37,7 +42,7 @@ if (isServer) {
return id
}
cancelAnimationFrame = function(id) {
cancelAnimationFrame = function (id) {
window.clearTimeout(id)
}
}

View File

@ -1,191 +1,202 @@
<template>
<span>
{{displayValue}}
</span>
<span>
{{ displayValue }}
</span>
</template>
<script lang="ts">
import { requestAnimationFrame, cancelAnimationFrame } from './requestAnimationFrame.js'
export default {
props: {
startVal: {
type: Number,
required: false,
default: 0
import { requestAnimationFrame, cancelAnimationFrame } from './requestAnimationFrame.js'
export default {
props: {
startVal: {
type: Number,
required: false,
default: 0,
},
endVal: {
type: Number,
required: false,
default: 2017,
},
duration: {
type: Number,
required: false,
default: 3000,
},
autoplay: {
type: Boolean,
required: false,
default: true,
},
decimals: {
type: Number,
required: false,
default: 0,
validator(value) {
return value >= 0
},
},
decimal: {
type: String,
required: false,
default: '.',
},
separator: {
type: String,
required: false,
default: ',',
},
prefix: {
type: String,
required: false,
default: '',
},
suffix: {
type: String,
required: false,
default: '',
},
useEasing: {
type: Boolean,
required: false,
default: true,
},
easingFn: {
type: Function,
default(t, b, c, d) {
return (c * (-Math.pow(2, (-10 * t) / d) + 1) * 1024) / 1023 + b
},
},
},
endVal: {
type: Number,
required: false,
default: 2017
},
duration: {
type: Number,
required: false,
default: 3000
},
autoplay: {
type: Boolean,
required: false,
default: true
},
decimals: {
type: Number,
required: false,
default: 0,
validator(value) {
return value >= 0
data() {
return {
localStartVal: this.startVal,
displayValue: this.formatNumber(this.startVal),
printVal: null,
paused: false,
localDuration: this.duration,
startTime: null,
timestamp: null,
remaining: null,
rAF: null,
}
},
decimal: {
type: String,
required: false,
default: '.'
computed: {
countDown() {
return this.startVal > this.endVal
},
},
separator: {
type: String,
required: false,
default: ','
watch: {
startVal() {
if (this.autoplay) {
this.start()
}
},
endVal() {
if (this.autoplay) {
this.start()
}
},
},
prefix: {
type: String,
required: false,
default: ''
},
suffix: {
type: String,
required: false,
default: ''
},
useEasing: {
type: Boolean,
required: false,
default: true
},
easingFn: {
type: Function,
default(t, b, c, d) {
return c * (-Math.pow(2, -10 * t / d) + 1) * 1024 / 1023 + b;
}
}
},
data() {
return {
localStartVal: this.startVal,
displayValue: this.formatNumber(this.startVal),
printVal: null,
paused: false,
localDuration: this.duration,
startTime: null,
timestamp: null,
remaining: null,
rAF: null
};
},
computed: {
countDown() {
return this.startVal > this.endVal
}
},
watch: {
startVal() {
mounted() {
if (this.autoplay) {
this.start();
this.start()
}
this.$emit('mountedCallback')
},
endVal() {
if (this.autoplay) {
this.start();
}
}
},
mounted() {
if (this.autoplay) {
this.start();
}
this.$emit('mountedCallback')
},
methods: {
start() {
this.localStartVal = this.startVal;
this.startTime = null;
this.localDuration = this.duration;
this.paused = false;
this.rAF = requestAnimationFrame(this.count);
},
pauseResume() {
if (this.paused) {
this.resume();
this.paused = false;
} else {
this.pause();
this.paused = true;
}
},
pause() {
cancelAnimationFrame(this.rAF);
},
resume() {
this.startTime = null;
this.localDuration = +this.remaining;
this.localStartVal = +this.printVal;
requestAnimationFrame(this.count);
},
reset() {
this.startTime = null;
cancelAnimationFrame(this.rAF);
this.displayValue = this.formatNumber(this.startVal);
},
count(timestamp) {
if (!this.startTime) this.startTime = timestamp;
this.timestamp = timestamp;
const progress = timestamp - this.startTime;
this.remaining = this.localDuration - progress;
if (this.useEasing) {
if (this.countDown) {
this.printVal = this.localStartVal - this.easingFn(progress, 0, this.localStartVal - this.endVal, this.localDuration)
methods: {
start() {
this.localStartVal = this.startVal
this.startTime = null
this.localDuration = this.duration
this.paused = false
this.rAF = requestAnimationFrame(this.count)
},
pauseResume() {
if (this.paused) {
this.resume()
this.paused = false
} else {
this.printVal = this.easingFn(progress, this.localStartVal, this.endVal - this.localStartVal, this.localDuration);
this.pause()
this.paused = true
}
} else {
if (this.countDown) {
this.printVal = this.localStartVal - ((this.localStartVal - this.endVal) * (progress / this.localDuration));
} else {
this.printVal = this.localStartVal + (this.endVal - this.localStartVal) * (progress / this.localDuration);
}
}
if (this.countDown) {
this.printVal = this.printVal < this.endVal ? this.endVal : this.printVal;
} else {
this.printVal = this.printVal > this.endVal ? this.endVal : this.printVal;
}
},
pause() {
cancelAnimationFrame(this.rAF)
},
resume() {
this.startTime = null
this.localDuration = +this.remaining
this.localStartVal = +this.printVal
requestAnimationFrame(this.count)
},
reset() {
this.startTime = null
cancelAnimationFrame(this.rAF)
this.displayValue = this.formatNumber(this.startVal)
},
count(timestamp) {
if (!this.startTime) this.startTime = timestamp
this.timestamp = timestamp
const progress = timestamp - this.startTime
this.remaining = this.localDuration - progress
this.displayValue = this.formatNumber(this.printVal)
if (progress < this.localDuration) {
this.rAF = requestAnimationFrame(this.count);
} else {
this.$emit('callback');
}
},
isNumber(val) {
return !isNaN(parseFloat(val))
},
formatNumber(num) {
num = num.toFixed(this.decimals);
num += '';
const x = num.split('.');
let x1 = x[0];
const x2 = x.length > 1 ? this.decimal + x[1] : '';
const rgx = /(\d+)(\d{3})/;
if (this.separator && !this.isNumber(this.separator)) {
while (rgx.test(x1)) {
x1 = x1.replace(rgx, '$1' + this.separator + '$2');
if (this.useEasing) {
if (this.countDown) {
this.printVal =
this.localStartVal -
this.easingFn(progress, 0, this.localStartVal - this.endVal, this.localDuration)
} else {
this.printVal = this.easingFn(
progress,
this.localStartVal,
this.endVal - this.localStartVal,
this.localDuration,
)
}
} else {
if (this.countDown) {
this.printVal =
this.localStartVal -
(this.localStartVal - this.endVal) * (progress / this.localDuration)
} else {
this.printVal =
this.localStartVal +
(this.endVal - this.localStartVal) * (progress / this.localDuration)
}
}
}
return this.prefix + x1 + x2 + this.suffix;
}
},
destroyed() {
cancelAnimationFrame(this.rAF)
if (this.countDown) {
this.printVal = this.printVal < this.endVal ? this.endVal : this.printVal
} else {
this.printVal = this.printVal > this.endVal ? this.endVal : this.printVal
}
this.displayValue = this.formatNumber(this.printVal)
if (progress < this.localDuration) {
this.rAF = requestAnimationFrame(this.count)
} else {
this.$emit('callback')
}
},
isNumber(val) {
return !isNaN(parseFloat(val))
},
formatNumber(num) {
num = num.toFixed(this.decimals)
num += ''
const x = num.split('.')
let x1 = x[0]
const x2 = x.length > 1 ? this.decimal + x[1] : ''
const rgx = /(\d+)(\d{3})/
if (this.separator && !this.isNumber(this.separator)) {
while (rgx.test(x1)) {
x1 = x1.replace(rgx, '$1' + this.separator + '$2')
}
}
return this.prefix + x1 + x2 + this.suffix
},
},
destroyed() {
cancelAnimationFrame(this.rAF)
},
}
};
</script>

View File

@ -1,65 +1,66 @@
<template>
<div class="m-info">
<el-popover
width="200px"
placement="bottom"
>
<template #reference>
<el-badge :value="3" class="item-info-pop">
<el-icon class="bell"><Bell /></el-icon>
</el-badge>
</template>
<div>
<el-tabs v-model="activeName" class="demo-tabs" @tab-click="handleClick">
<el-tab-pane label="通知" name="first">
<div class="item-child"> github开源地址<el-button type="primary" link @click="toGitHub">点我</el-button></div>
<div class="item-child"> github开源地址<el-button type="primary" link @click="toGitHub">点我</el-button></div>
<div class="item-child"> github开源地址<el-button type="primary" link @click="toGitHub">点我</el-button></div>
</el-tab-pane>
</el-tabs>
</div>
</el-popover>
</div>
<div class="m-info">
<el-popover width="200px" placement="bottom">
<template #reference>
<el-badge :value="3" class="item-info-pop">
<el-icon class="bell"><Bell /></el-icon>
</el-badge>
</template>
<div>
<el-tabs v-model="activeName" class="demo-tabs" @tab-click="handleClick">
<el-tab-pane label="通知" name="first">
<div class="item-child">
github开源地址<el-button type="primary" link @click="toGitHub">点我</el-button></div
>
<div class="item-child">
github开源地址<el-button type="primary" link @click="toGitHub">点我</el-button></div
>
<div class="item-child">
github开源地址<el-button type="primary" link @click="toGitHub">点我</el-button></div
>
</el-tab-pane>
</el-tabs>
</div>
</el-popover>
</div>
</template>
<script lang="ts" setup>
import { ref } from 'vue'
import type { TabsPaneContext } from 'element-plus'
import { ref } from 'vue'
import type { TabsPaneContext } from 'element-plus'
const activeName = ref('first')
const toGitHub = () => {
window.open('https://github.com/zouzhibin/vue-admin-perfect')
}
const handleClick = (tab: TabsPaneContext, event: Event) => {
console.log(tab, event)
}
const activeName = ref('first')
const toGitHub = () => {
window.open('https://github.com/zouzhibin/vue-admin-perfect')
}
const handleClick = (tab: TabsPaneContext, event: Event) => {
console.log(tab, event)
}
</script>
<style lang="scss" scoped>
.m-info{
.m-info {
width: 40px;
display: inline-flex;
align-items: center;
justify-content: center;
cursor: pointer;
transition: all .3s;
.item-info-pop{
transition: all 0.3s;
.item-info-pop {
// width:100% ;
//height: 100%;
display: flex;
align-items: center;
}
.item-child{
display: flex;
align-items: center;
font-size: 13px;
.item-child {
display: flex;
align-items: center;
font-size: 13px;
}
}
.transverseMenu {
.bell {
color: white;
}
}
.transverseMenu{
.bell{
color: white;
}
}
</style>

View File

@ -1,7 +1,3 @@
<template>
<template> </template>
</template>
<script lang="ts">
</script>
<script lang="ts"></script>

View File

@ -1,91 +1,94 @@
<template>
<div class="g-right-click-menu" :style="style" v-if="isShow" ref="rightMenu">
<div
v-for="item,index in data"
:key="index"
class="operating" @click.stop="operatingRightAction($event,item)">{{item.label}}</div>
v-for="(item, index) in data"
:key="index"
class="operating"
@click.stop="operatingRightAction($event, item)"
>{{ item.label }}</div
>
</div>
</template>
<script lang="ts">
export default {
props: {
data:{
type:Array,
default:()=>[]
export default {
props: {
data: {
type: Array,
default: () => [],
},
left: {
type: Number,
default: 0,
},
type: {
type: Number,
default: 1,
},
dataInfo: {
type: Object,
default: () => {},
},
top: {
type: Number,
default: 0,
},
isViewInfo: {
type: Boolean,
default: true,
},
},
left: {
type: Number,
default: 0
watch: {
left: {
handler(newName, oldName) {
if (newName) {
this.isShow = true
}
},
// wacthfirstNamehandler
// immediate: true
},
},
type: {
type: Number,
default: 1
},
dataInfo: {
type: Object,
default: () => {}
},
top: {
type: Number,
default: 0
},
isViewInfo: {
type: Boolean,
default: true
}
},
watch: {
left: {
handler (newName, oldName) {
if (newName) {
this.isShow = true
computed: {
style() {
let clientHeight = document.body.clientHeight
let y = this.top
if (clientHeight - y < 100) {
return `left:${this.left}px;bottom:${clientHeight - y}px`
} else {
return `left:${this.left}px;top:${this.top}px`
}
},
},
data() {
return {
isShow: false,
}
// wacthfirstNamehandler
// immediate: true
}
},
computed: {
style () {
let clientHeight = document.body.clientHeight
let y = this.top
if (clientHeight - y < 100) {
return `left:${this.left}px;bottom:${clientHeight - y}px`
} else {
return `left:${this.left}px;top:${this.top}px`
}
}
},
data () {
return {
isShow: false
}
},
methods: {
/**
},
methods: {
/**
* @func 点击操作
* @param val 1置顶/取消置顶 2开启/关闭免打扰 3开启/关闭星标 4删除会话
*/
operatingRightAction ($event, val) {
this.$emit('ok', $event, val)
this.isShow = false
}
},
mounted () {
let _self = this
window.addEventListener('click', function () {
_self.isShow = false
})
window.addEventListener('mousedown', function (e) {
if (e.which === 3) {
operatingRightAction($event, val) {
this.$emit('ok', $event, val)
this.isShow = false
},
},
mounted() {
let _self = this
window.addEventListener('click', function () {
_self.isShow = false
}
})
})
window.addEventListener('mousedown', function (e) {
if (e.which === 3) {
_self.isShow = false
}
})
},
}
}
</script>
<style lang="scss" scoped>
.g-right-click-menu {
.g-right-click-menu {
left: 0;
background: white;
width: 148px;
@ -94,19 +97,19 @@ export default {
//border: 1px solid #c4c4c4;
z-index: 9;
//box-shadow: 0 1px 2px 0px rgba(0, 0, 0, 0.1);
box-shadow: 0 2px 12px 0 rgb(0 0 0 / 10%);
box-shadow: 0 2px 12px 0 rgb(0 0 0 / 10%);
.operating {
font-size: 12px;
padding-left: 23px;
cursor: pointer;
line-height: 27px;
font-size: 12px;
padding-left: 23px;
cursor: pointer;
line-height: 27px;
}
.operating:hover {
background: #e2e2e2;
background: #e2e2e2;
}
.last-delete {
border-top: 1px solid #ededed;
border-top: 1px solid #ededed;
}
}
}
</style>

View File

@ -1,157 +1,154 @@
/* eslint-disable promise/prefer-await-to-then */
const methodMap = [
[
'requestFullscreen',
'exitFullscreen',
'fullscreenElement',
'fullscreenEnabled',
'fullscreenchange',
'fullscreenerror',
],
// New WebKit
[
'webkitRequestFullscreen',
'webkitExitFullscreen',
'webkitFullscreenElement',
'webkitFullscreenEnabled',
'webkitfullscreenchange',
'webkitfullscreenerror',
],
// Old WebKit
[
'webkitRequestFullScreen',
'webkitCancelFullScreen',
'webkitCurrentFullScreenElement',
'webkitCancelFullScreen',
'webkitfullscreenchange',
'webkitfullscreenerror',
],
[
'mozRequestFullScreen',
'mozCancelFullScreen',
'mozFullScreenElement',
'mozFullScreenEnabled',
'mozfullscreenchange',
'mozfullscreenerror',
],
[
'msRequestFullscreen',
'msExitFullscreen',
'msFullscreenElement',
'msFullscreenEnabled',
'MSFullscreenChange',
'MSFullscreenError',
],
];
[
'requestFullscreen',
'exitFullscreen',
'fullscreenElement',
'fullscreenEnabled',
'fullscreenchange',
'fullscreenerror',
],
// New WebKit
[
'webkitRequestFullscreen',
'webkitExitFullscreen',
'webkitFullscreenElement',
'webkitFullscreenEnabled',
'webkitfullscreenchange',
'webkitfullscreenerror',
],
// Old WebKit
[
'webkitRequestFullScreen',
'webkitCancelFullScreen',
'webkitCurrentFullScreenElement',
'webkitCancelFullScreen',
'webkitfullscreenchange',
'webkitfullscreenerror',
],
[
'mozRequestFullScreen',
'mozCancelFullScreen',
'mozFullScreenElement',
'mozFullScreenEnabled',
'mozfullscreenchange',
'mozfullscreenerror',
],
[
'msRequestFullscreen',
'msExitFullscreen',
'msFullscreenElement',
'msFullscreenEnabled',
'MSFullscreenChange',
'MSFullscreenError',
],
]
const nativeAPI = (() => {
const unprefixedMethods = methodMap[0];
const returnValue = {};
const unprefixedMethods = methodMap[0]
const returnValue = {}
for (const methodList of methodMap) {
const exitFullscreenMethod = methodList?.[1];
if (exitFullscreenMethod in document) {
for (const [index, method] of methodList.entries()) {
returnValue[unprefixedMethods[index]] = method;
}
for (const methodList of methodMap) {
const exitFullscreenMethod = methodList?.[1]
if (exitFullscreenMethod in document) {
for (const [index, method] of methodList.entries()) {
returnValue[unprefixedMethods[index]] = method
}
return returnValue;
}
}
return returnValue
}
}
return false;
})();
return false
})()
const eventNameMap = {
change: nativeAPI.fullscreenchange,
error: nativeAPI.fullscreenerror,
};
change: nativeAPI.fullscreenchange,
error: nativeAPI.fullscreenerror,
}
// eslint-disable-next-line import/no-mutable-exports
let screenfull = {
// eslint-disable-next-line default-param-last
request(element = document.documentElement, options) {
return new Promise((resolve, reject) => {
const onFullScreenEntered = () => {
screenfull.off('change', onFullScreenEntered);
resolve();
};
// eslint-disable-next-line default-param-last
request(element = document.documentElement, options) {
return new Promise((resolve, reject) => {
const onFullScreenEntered = () => {
screenfull.off('change', onFullScreenEntered)
resolve()
}
screenfull.on('change', onFullScreenEntered);
screenfull.on('change', onFullScreenEntered)
const returnPromise = element[nativeAPI.requestFullscreen](options);
const returnPromise = element[nativeAPI.requestFullscreen](options)
if (returnPromise instanceof Promise) {
returnPromise.then(onFullScreenEntered).catch(reject);
}
});
},
exit() {
return new Promise((resolve, reject) => {
if (!screenfull.isFullscreen) {
resolve();
return;
}
if (returnPromise instanceof Promise) {
returnPromise.then(onFullScreenEntered).catch(reject)
}
})
},
exit() {
return new Promise((resolve, reject) => {
if (!screenfull.isFullscreen) {
resolve()
return
}
const onFullScreenExit = () => {
screenfull.off('change', onFullScreenExit);
resolve();
};
const onFullScreenExit = () => {
screenfull.off('change', onFullScreenExit)
resolve()
}
screenfull.on('change', onFullScreenExit);
screenfull.on('change', onFullScreenExit)
const returnPromise = document[nativeAPI.exitFullscreen]();
const returnPromise = document[nativeAPI.exitFullscreen]()
if (returnPromise instanceof Promise) {
returnPromise.then(onFullScreenExit).catch(reject);
}
});
},
toggle(element, options) {
return screenfull.isFullscreen ? screenfull.exit() : screenfull.request(element, options);
},
onchange(callback) {
screenfull.on('change', callback);
},
onerror(callback) {
screenfull.on('error', callback);
},
on(event, callback) {
const eventName = eventNameMap[event];
if (eventName) {
document.addEventListener(eventName, callback, false);
}
},
off(event, callback) {
const eventName = eventNameMap[event];
if (eventName) {
document.removeEventListener(eventName, callback, false);
}
},
raw: nativeAPI,
};
Object.defineProperties(screenfull, {
isFullscreen: {
get: () => Boolean(document[nativeAPI.fullscreenElement]),
},
element: {
enumerable: true,
get: () => document[nativeAPI.fullscreenElement] ?? undefined,
},
isEnabled: {
enumerable: true,
// Coerce to boolean in case of old WebKit.
get: () => Boolean(document[nativeAPI.fullscreenEnabled]),
},
});
if (!nativeAPI) {
screenfull = {isEnabled: false};
if (returnPromise instanceof Promise) {
returnPromise.then(onFullScreenExit).catch(reject)
}
})
},
toggle(element, options) {
return screenfull.isFullscreen ? screenfull.exit() : screenfull.request(element, options)
},
onchange(callback) {
screenfull.on('change', callback)
},
onerror(callback) {
screenfull.on('error', callback)
},
on(event, callback) {
const eventName = eventNameMap[event]
if (eventName) {
document.addEventListener(eventName, callback, false)
}
},
off(event, callback) {
const eventName = eventNameMap[event]
if (eventName) {
document.removeEventListener(eventName, callback, false)
}
},
raw: nativeAPI,
}
Object.defineProperties(screenfull, {
isFullscreen: {
get: () => Boolean(document[nativeAPI.fullscreenElement]),
},
element: {
enumerable: true,
get: () => document[nativeAPI.fullscreenElement] ?? undefined,
},
isEnabled: {
enumerable: true,
// Coerce to boolean in case of old WebKit.
get: () => Boolean(document[nativeAPI.fullscreenEnabled]),
},
})
export default screenfull;
if (!nativeAPI) {
screenfull = { isEnabled: false }
}
export default screenfull

View File

@ -1,66 +1,67 @@
<template>
<div class="m-screenful">
<el-icon
class="full-screen"
title="全屏"
@click.stop="click"
style="margin-right: 10px;cursor: pointer" ><full-screen /></el-icon>
class="full-screen"
title="全屏"
@click.stop="click"
style="margin-right: 10px; cursor: pointer"
><full-screen
/></el-icon>
</div>
</template>
<script lang="ts" setup>
import screenfull from './index'
import { ElMessage } from 'element-plus'
import {onBeforeUnmount, onMounted, ref} from "vue";
import { onBeforeUnmount, onMounted, ref } from 'vue'
let isFullscreen = ref(false)
const click = ()=>{
const click = () => {
if (!screenfull.isEnabled) {
ElMessage({
message: '你的浏览器不支持',
type: 'warning'
type: 'warning',
})
return false
}
screenfull.toggle()
}
const change = ()=>{
const change = () => {
isFullscreen.value = screenfull.isFullscreen
}
const init = ()=>{
const init = () => {
if (screenfull.isEnabled) {
screenfull.on('change', change)
}
}
const destroy = ()=>{
const destroy = () => {
if (screenfull.isEnabled) {
screenfull.off('change', change)
}
}
onMounted(()=>{
onMounted(() => {
init()
})
onBeforeUnmount(()=>{
onBeforeUnmount(() => {
destroy()
})
</script>
<style lang="scss" scoped>
.m-screenful{
.m-screenful {
width: 40px;
display: inline-flex;
align-items: center;
justify-content: center;
cursor: pointer;
transition: all .3s;
transition: all 0.3s;
}
.transverseMenu{
.full-screen{
.transverseMenu {
.full-screen {
color: white;
}
}

View File

@ -1,126 +1,126 @@
<template>
<div>
<div class="m-setting-fix">
<div class="item">
<div class="item-child" @click="operator(1)">
<el-icon size="30" color="#3698fd" style="margin-bottom: 8px"><brush /></el-icon>
主题配置
</div>
<div class="item-child item-child2" @click="operator(2)">
<el-icon size="30"
color="#3698fd"
style="margin-bottom: 8px"><Link /></el-icon>
源码拷贝
</div>
</div>
<div>
<div class="m-setting-fix">
<div class="item">
<div class="item-child" @click="operator(1)">
<el-icon size="30" color="#3698fd" style="margin-bottom: 8px"><brush /></el-icon>
主题配置
</div>
<el-drawer v-model="drawer" title="主题配置" size="300px">
<div class="drawer-item">
<label>布局</label>
<el-select v-model="layout" placeholder="请选择" style="width: 150px" @change="(val)=>changeSwitch(val,2)">
<el-option label="纵向" value="vertical"></el-option>
<el-option label="横向" value="horizontal"></el-option>
</el-select>
</div>
<div class="drawer-item">
<label>标签</label>
<el-switch v-model="tag" @change="(val)=>changeSwitch(val,1)"/>
</div>
</el-drawer>
<div class="item-child item-child2" @click="operator(2)">
<el-icon size="30" color="#3698fd" style="margin-bottom: 8px"><Link /></el-icon>
源码拷贝
</div>
</div>
</div>
<el-drawer v-model="drawer" title="主题配置" size="300px">
<div class="drawer-item">
<label>布局</label>
<el-select
v-model="layout"
placeholder="请选择"
style="width: 150px"
@change="(val) => changeSwitch(val, 2)"
>
<el-option label="纵向" value="vertical"></el-option>
<el-option label="横向" value="horizontal"></el-option>
</el-select>
</div>
<div class="drawer-item">
<label>标签</label>
<el-switch v-model="tag" @change="(val) => changeSwitch(val, 1)" />
</div>
</el-drawer>
</div>
</template>
<script lang="ts" setup>
import { ref } from 'vue'
const drawer = ref(false)
const tag = ref(true)
const layout = ref('vertical')
import {useStore} from "vuex";
import { ref } from 'vue'
const drawer = ref(false)
const tag = ref(true)
const layout = ref('vertical')
import { useStore } from 'vuex'
const store = useStore()
const operator = (type)=>{
switch (type) {
case 1:
drawer.value = true
return
case 2:
window.open('https://github.com/zouzhibin/vue-admin-perfect')
return
}
const store = useStore()
const operator = (type) => {
switch (type) {
case 1:
drawer.value = true
return
case 2:
window.open('https://github.com/zouzhibin/vue-admin-perfect')
return
}
}
const changeSwitch =(val,type)=>{
switch (type) {
// tag
case 1:
store.dispatch('setting/setTag',val)
return
case 2:
store.dispatch('setting/setMode',val)
return
}
const changeSwitch = (val, type) => {
switch (type) {
// tag
case 1:
store.dispatch('setting/setTag', val)
return
case 2:
store.dispatch('setting/setMode', val)
return
}
}
</script>
<style lang="scss" scoped>
.m-setting-fix{
.m-setting-fix {
position: fixed;
top: 50%;
right: 0;
z-index: 1997;
padding: 10px 0 0 0;
margin: 0;
text-align: center;
cursor: pointer;
background: #fff;
border: 1px solid #dcdfe6;
border-top-left-radius: 5.5px;
border-bottom-left-radius: 5.5px;
box-shadow: 0 0 50px 0 rgb(82 63 105 / 15%);
transform: translateY(-50%);
.item{
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 0 8px 10px 10px;
margin: 0;
list-style: none;
}
.item-child{
color: #3698fd;
width: 60px;
height: 60px;
/*padding-top: 10px;*/
text-align: center;
display: flex;
flex-direction: column;
background: #f6f8f9;
align-items: center;
justify-content: center;
border-radius: 5.5px;
font-size: 12px;
background: #ebf5ff;
transition: color .15s ease,background-color .15s ease,border-color .15s ease,box-shadow .15s ease;
top: 50%;
right: 0;
z-index: 1997;
padding: 10px 0 0 0;
margin: 0;
text-align: center;
cursor: pointer;
background: #fff;
border: 1px solid #dcdfe6;
border-top-left-radius: 5.5px;
border-bottom-left-radius: 5.5px;
box-shadow: 0 0 50px 0 rgb(82 63 105 / 15%);
transform: translateY(-50%);
.item {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 0 8px 10px 10px;
margin: 0;
list-style: none;
}
.item-child2{
margin-top: 10px;
color: #b37feb;
background: #f7f2fd;
transition: color .15s ease,background-color .15s ease,border-color .15s ease,box-shadow .15s ease;
.item-child {
color: #3698fd;
width: 60px;
height: 60px;
/*padding-top: 10px;*/
text-align: center;
display: flex;
flex-direction: column;
background: #f6f8f9;
align-items: center;
justify-content: center;
border-radius: 5.5px;
font-size: 12px;
background: #ebf5ff;
transition: color 0.15s ease, background-color 0.15s ease, border-color 0.15s ease,
box-shadow 0.15s ease;
}
}
.drawer-item{
.item-child2 {
margin-top: 10px;
color: #b37feb;
background: #f7f2fd;
transition: color 0.15s ease, background-color 0.15s ease, border-color 0.15s ease,
box-shadow 0.15s ease;
}
}
.drawer-item {
width: 100%;
display: flex;
margin-bottom: 15px;
align-items: center;
justify-content: space-between;
}
</style>
}
</style>

View File

@ -1,86 +1,88 @@
<template>
<el-upload
action=""
:before-upload="beforeUploadAction"
:list-type="listType"
:multiple="multiple"
:on-preview="handlePictureCardPreview"
:on-remove="handleRemove"
:file-list="fileList"
>
<el-icon><Plus /></el-icon>
</el-upload>
<el-upload
action=""
:before-upload="beforeUploadAction"
:list-type="listType"
:multiple="multiple"
:on-preview="handlePictureCardPreview"
:on-remove="handleRemove"
:file-list="fileList"
>
<el-icon><Plus /></el-icon>
</el-upload>
<el-dialog v-model="dialogVisible" width="50%" top="80px">
<img w-full :src="dialogImageUrl" alt="预览图片" style="width: 100%"/>
</el-dialog>
<el-dialog v-model="dialogVisible" width="50%" top="80px">
<img w-full :src="dialogImageUrl" alt="预览图片" style="width: 100%" />
</el-dialog>
</template>
<script lang="ts" setup>
import {onMounted, ref, watch} from 'vue'
import { Plus } from '@element-plus/icons-vue'
import { onMounted, ref, watch } from 'vue'
import { Plus } from '@element-plus/icons-vue'
import type { UploadProps, UploadUserFile } from 'element-plus'
import {ElMessage} from "element-plus";
let emit = defineEmits(['update'])
let props = defineProps({
modelValue:Array,
multiple:{
type:Boolean,
default:true
},
listType:{
type:String,
default:'picture-card'
},
showFileList:{
type:Boolean,
default:true
import type { UploadProps, UploadUserFile } from 'element-plus'
import { ElMessage } from 'element-plus'
let emit = defineEmits(['update'])
let props = defineProps({
modelValue: Array,
multiple: {
type: Boolean,
default: true,
},
listType: {
type: String,
default: 'picture-card',
},
showFileList: {
type: Boolean,
default: true,
},
})
let fileList = ref([])
const dialogImageUrl = ref('')
const dialogVisible = ref(false)
const handleRemove: UploadProps['onRemove'] = (uploadFile, uploadFiles) => {
console.log(uploadFile, uploadFiles)
}
const beforeUploadAction = (file, fileLi) => {
return new Promise((resolve, reject) => {
var reader = new FileReader()
let reg = /\.jpg$|\.jpeg$|\.gif$|\.png$/i
reader.readAsDataURL(file)
let name = file.name
if (reg.test(name)) {
reader.onload = (e: FileReader) => {
fileList.value.push({
name: name,
url: e.target.result,
})
emit('update', fileList.value)
resolve(e.target.result)
}
} else {
ElMessage.error('请上传图片')
reject()
}
})
let fileList = ref([
}
])
const handlePictureCardPreview: UploadProps['onPreview'] = (uploadFile) => {
dialogImageUrl.value = uploadFile.url!
dialogVisible.value = true
}
const dialogImageUrl = ref('')
const dialogVisible = ref(false)
const handleRemove: UploadProps['onRemove'] = (uploadFile, uploadFiles) => {
console.log(uploadFile, uploadFiles)
}
const beforeUploadAction = (file, fileLi)=>{
return new Promise((resolve, reject) => {
var reader = new FileReader()
let reg = (/\.jpg$|\.jpeg$|\.gif$|\.png$/i)
reader.readAsDataURL(file)
let name = file.name
if(reg.test(name)){
reader.onload = (e:FileReader)=>{
fileList.value.push({
name:name,
url:e.target.result
})
emit('update',fileList.value)
resolve(e.target.result)
}
}else{
ElMessage.error('请上传图片')
reject()
}
})
}
const handlePictureCardPreview: UploadProps['onPreview'] = (uploadFile) => {
dialogImageUrl.value = uploadFile.url!
dialogVisible.value = true
}
onMounted(()=>{
watch(()=>props.modelValue,(value)=>{
fileList.value = value
},{
immediate:true
})
})
onMounted(() => {
watch(
() => props.modelValue,
(value) => {
fileList.value = value
},
{
immediate: true,
},
)
})
</script>

View File

@ -4,45 +4,44 @@
</div>
</template>
<script lang="ts" setup>
// wangEditor
import wangEditor from 'wangeditor'
import {onBeforeUnmount, onMounted, watch} from "vue";
let editors = null
// wangEditor
import wangEditor from 'wangeditor'
import { onBeforeUnmount, onMounted, watch } from 'vue'
let editors = null
let emit = defineEmits(['update:modelValue'])
let props = defineProps({
modelValue:String
})
const getEditorData = () =>{
//
let data = editors.txt.html()
alert(data)
}
onMounted(()=>{
watch(()=>props.modelValue,(value)=>{
editors.txt.html(value)
let emit = defineEmits(['update:modelValue'])
let props = defineProps({
modelValue: String,
})
const editor = new wangEditor(`#wangEditor`)
// onchange vue
editor.config.onchange = (newHtml) => {
emit('update:modelValue',newHtml)
const getEditorData = () => {
//
let data = editors.txt.html()
alert(data)
}
//
editor.create()
editors = editor
})
onMounted(() => {
watch(
() => props.modelValue,
(value) => {
editors.txt.html(value)
},
)
const editor = new wangEditor(`#wangEditor`)
// onchange vue
editor.config.onchange = (newHtml) => {
emit('update:modelValue', newHtml)
}
//
editor.create()
onBeforeUnmount(()=>{
// API
editors.destroy()
editors = null
})
editors = editor
})
onBeforeUnmount(() => {
// API
editors.destroy()
editors = null
})
</script>
<style>
</style>
<style></style>

View File

@ -1,11 +1,11 @@
import Vue from 'vue'
import SvgIcon from '@/components/SvgIcon'// svg component
import SvgIcon from '@/components/SvgIcon' // svg component
console.log(11111111)
// const req = require.context('./svg', false, /\.svg$/)
const req = import.meta.globEager('./svg/*.svg')
consoole.log('req',req)
const requireAll = requireContext => requireContext.keys().map(requireContext)
consoole.log('req', req)
const requireAll = (requireContext) => requireContext.keys().map(requireContext)
requireAll(req)
export default SvgIcon

View File

@ -1,34 +1,34 @@
<template>
<section class="app-main" v-if="isReload">
<router-view v-slot="{ Component,route }">
<transition name="fade-slide" mode="out-in" appear>
<keep-alive v-if="route.meta&&route.meta.keepAlive">
<component :is="Component" :key="route.path" />
</keep-alive>
<component :is="Component" :key="route.path" v-else/>
</transition>
</router-view>
<u-setting/>
<section class="app-main" v-if="isReload">
<router-view v-slot="{ Component, route }">
<transition name="fade-slide" mode="out-in" appear>
<keep-alive v-if="route.meta && route.meta.keepAlive">
<component :is="Component" :key="route.path" />
</keep-alive>
<component :is="Component" :key="route.path" v-else />
</transition>
</router-view>
<u-setting />
</section>
</template>
<script lang="ts" setup>
import USetting from '@/components/u-setting/index.vue'
import { useStore } from 'vuex'
import { computed, ref } from 'vue'
const store = useStore()
import USetting from '@/components/u-setting/index.vue'
import { useStore } from 'vuex'
import { computed, ref } from 'vue'
const store = useStore()
const cachedViews = computed(() => {
return store.state.tagsView.cachedViews
})
const cachedViews = computed(() => {
return store.state.tagsView.cachedViews
})
const isReload = computed(() => {
return store.state.app.isReload
})
const isReload = computed(() => {
return store.state.app.isReload
})
</script>
<style lang="scss" scoped>
.app-main{
.app-main {
//padding: 20px;
/*padding-top: 110px;*/
//min-height: 100%;

View File

@ -5,45 +5,45 @@
</template>
<script lang="ts">
import { isExternal } from '@/utils/validate.js'
import { isExternal } from '@/utils/validate.js'
export default {
props: {
to: {
type: String,
required: true
}
},
computed: {
isExternal() {
return isExternal(this.to)
export default {
props: {
to: {
type: String,
required: true,
},
},
type() {
if (this.isExternal) {
return 'a'
}
return 'router-link'
}
},
methods: {
linkProps(to) {
if (this.isExternal) {
return {
href: to,
target: '_blank',
rel: 'noopener'
computed: {
isExternal() {
return isExternal(this.to)
},
type() {
if (this.isExternal) {
return 'a'
}
}
return {
to: to
}
}
return 'router-link'
},
},
methods: {
linkProps(to) {
if (this.isExternal) {
return {
href: to,
target: '_blank',
rel: 'noopener',
}
}
return {
to: to,
}
},
},
}
}
</script>
<style lang="scss" scoped>
a{
text-decoration: none;
}
a {
text-decoration: none;
}
</style>

View File

@ -1,78 +1,77 @@
<template>
<div class="sidebar-logo-container" :class="{'collapse':isCollapse}">
<div class="sidebar-logo-container" :class="{ collapse: isCollapse }">
<transition name="sidebarLogoFade">
<router-link v-if="isCollapse" key="collapse" class="sidebar-logo-link" to="/">
<img v-if="logo" :src="logo" class="sidebar-logo">
<img v-if="logo" :src="logo" class="sidebar-logo" />
<h1 v-else class="sidebar-title">Perfect </h1>
</router-link>
<router-link v-else key="expand" class="sidebar-logo-link" to="/">
<img v-if="logo" :src="logo" class="sidebar-logo">
<h1 class="sidebar-title"> {{title}}</h1>
<img v-if="logo" :src="logo" class="sidebar-logo" />
<h1 class="sidebar-title"> {{ title }}</h1>
</router-link>
</transition>
</div>
</template>
<script lang="ts" setup>
import {computed, reactive, ref} from "vue";
import { useStore } from 'vuex' // useStore ===vue2.0this.$store
import logo from '@/assets/logo.png'
import { computed, reactive, ref } from 'vue'
import { useStore } from 'vuex' // useStore ===vue2.0this.$store
import logo from '@/assets/logo.png'
const store = useStore()
const title = ref<string>('Vue Admin Perfect')
const isCollapse = computed(()=>{
return !store.state.app.isCollapse
})
const store = useStore()
const title = ref<string>('Vue Admin Perfect')
const isCollapse = computed(() => {
return !store.state.app.isCollapse
})
</script>
<style lang="scss" scoped>
.sidebarLogoFade-enter-active {
transition: opacity 1.5s;
}
.sidebarLogoFade-enter-active {
transition: opacity 1.5s;
}
.sidebarLogoFade-enter,
.sidebarLogoFade-leave-to {
opacity: 0;
}
.sidebarLogoFade-enter,
.sidebarLogoFade-leave-to {
opacity: 0;
}
.sidebar-logo-container {
position: relative;
width: 100%;
height: 60px;
line-height: 60px;
background: #2b2f3a;
text-align: center;
overflow: hidden;
& .sidebar-logo-link {
height: 100%;
.sidebar-logo-container {
position: relative;
width: 100%;
height: 60px;
line-height: 60px;
background: #2b2f3a;
text-align: center;
overflow: hidden;
& .sidebar-logo {
width: 32px;
height: 32px;
vertical-align: middle;
margin-right: 12px;
& .sidebar-logo-link {
height: 100%;
width: 100%;
& .sidebar-logo {
width: 32px;
height: 32px;
vertical-align: middle;
margin-right: 12px;
}
& .sidebar-title {
display: inline-block;
margin: 0;
color: #fff;
font-weight: 600;
line-height: 50px;
font-size: 14px;
font-family: Avenir, Helvetica Neue, Arial, Helvetica, sans-serif;
vertical-align: middle;
}
}
& .sidebar-title {
display: inline-block;
margin: 0;
color: #fff;
font-weight: 600;
line-height: 50px;
font-size: 14px;
font-family: Avenir, Helvetica Neue, Arial, Helvetica, sans-serif;
vertical-align: middle;
&.collapse {
.sidebar-logo {
margin-right: 0px;
}
}
}
&.collapse {
.sidebar-logo {
margin-right: 0px;
}
}
}
</style>

View File

@ -1,49 +1,49 @@
<template>
<template v-if="!item.hidden">
<template v-if="!item.alwaysShow&&hasOneShowingChild(item.children,item)">
<template v-if="!item.alwaysShow && hasOneShowingChild(item.children, item)">
<app-link v-if="onlyOneChild.meta" :to="resolvePath(onlyOneChild.path)">
<el-menu-item :index="resolvePath(onlyOneChild.path)">
<el-icon :size="20">
<component :is="onlyOneChild?.meta.icon"></component>
</el-icon>
<template #title>{{ onlyOneChild.meta&&onlyOneChild.meta.title }}</template>
<template #title>{{ onlyOneChild.meta && onlyOneChild.meta.title }}</template>
</el-menu-item>
</app-link>
</template>
<el-sub-menu :index="resolvePath(item.path)" v-else popper-append-to-body>
<template #title>
<el-icon :size="20"> <component :is="item.meta?.icon"></component></el-icon>
<span>{{ item.meta&&item.meta.title }}</span>
<span>{{ item.meta && item.meta.title }}</span>
</template>
<sidebar-item
v-for="child in item.children"
:key="child.path"
:item="child"
:base-path="resolvePath(child.path)"
v-for="child in item.children"
:key="child.path"
:item="child"
:base-path="resolvePath(child.path)"
/>
</el-sub-menu>
</template>
</template>
<script lang="ts" setup >
<script lang="ts" setup>
import { isExternal } from '@/utils/validate.js'
import AppLink from './Link.vue'
import path from 'path-browserify'
import { ref,computed} from 'vue'
import { ref, computed } from 'vue'
const props = defineProps({
item:{
type:Object,
required: true
item: {
type: Object,
required: true,
},
basePath: {
type: String,
default: ''
}
default: '',
},
})
const onlyOneChild = ref(null)
const hasOneShowingChild = (children = [], parent)=>{
const showingChildren = children.filter(item => {
const hasOneShowingChild = (children = [], parent) => {
const showingChildren = children.filter((item) => {
//
if (item.hidden) {
return false
@ -60,15 +60,14 @@
}
//
if (showingChildren.length === 0) {
onlyOneChild.value = { ... parent, path: '', noShowingChildren: true }
onlyOneChild.value = { ...parent, path: '', noShowingChildren: true }
return true
}
return false
}
const resolvePath = (routePath)=>{
const resolvePath = (routePath) => {
if (isExternal(routePath)) {
return routePath
}
@ -77,5 +76,4 @@
}
return path.resolve(props.basePath, routePath)
}
</script>

View File

@ -1,8 +1,8 @@
<template>
<div :class="{'has-logo':isCollapse}">
<div :class="{ 'has-logo': isCollapse }">
<logo :collapse="isCollapse" />
<el-scrollbar wrap-class="scrollbar-wrapper">
<menu-slide/>
<menu-slide />
</el-scrollbar>
</div>
</template>
@ -10,27 +10,27 @@
<script lang="ts" setup>
import MenuSlide from './menuSlide.vue'
import logo from './Logo.vue'
import { useStore,mapGetters } from 'vuex' // useStore ===vue2.0this.$store
import { ref,computed } from 'vue'
import { useStore, mapGetters } from 'vuex' // useStore ===vue2.0this.$store
import { ref, computed } from 'vue'
// setupstore
const store = useStore()
//
const isCollapse = computed(()=>{
const isCollapse = computed(() => {
return !store.state.app.isCollapse
})
</script>
<style lang="scss">
.el-menu-vertical-demo:not(.el-menu--collapse) {
//width: 200px;
height: 100%;
}
.crollbar-wrapper{
height: 100%;
.el-scrollbar__view{
.el-menu-vertical-demo:not(.el-menu--collapse) {
//width: 200px;
height: 100%;
}
}
.crollbar-wrapper {
height: 100%;
.el-scrollbar__view {
height: 100%;
}
}
</style>

View File

@ -1,51 +1,56 @@
<template>
<el-menu
:default-active="activeMenu"
active-text-color="#ffd04b"
background-color="#304156"
text-color="#fff"
:mode="mode"
:collapse-transition="false"
class="el-menu-vertical-demo"
:collapse="isCollapse"
>
<sidebar-item v-for="route in permission_routes" :key="route.path" :item="route" :base-path="route.path"/>
</el-menu>
<el-menu
:default-active="activeMenu"
active-text-color="#ffd04b"
background-color="#304156"
text-color="#fff"
:mode="mode"
:collapse-transition="false"
class="el-menu-vertical-demo"
:collapse="isCollapse"
>
<sidebar-item
v-for="route in permission_routes"
:key="route.path"
:item="route"
:base-path="route.path"
/>
</el-menu>
</template>
<script lang="ts" setup>
import SidebarItem from './SidebarItem.vue'
import logo from './Logo.vue'
import {useRoute} from 'vue-router'
import { useStore,mapGetters } from 'vuex' // useStore ===vue2.0this.$store
import { ref,computed } from 'vue'
import SidebarItem from './SidebarItem.vue'
import logo from './Logo.vue'
import { useRoute } from 'vue-router'
import { useStore, mapGetters } from 'vuex' // useStore ===vue2.0this.$store
import { ref, computed } from 'vue'
// setupstore
const store = useStore()
const route = useRoute()
// setupstore
const store = useStore()
const route = useRoute()
//
const permission_routes = computed(()=>{
console.log('permission_routes',store.state.permission.routes)
return store.state.permission.routes
})
//
const permission_routes = computed(() => {
console.log('permission_routes', store.state.permission.routes)
return store.state.permission.routes
})
const activeMenu = computed(()=>{
const { meta, path } = route
// if set path, the sidebar will highlight the path you set
if (meta.activeMenu) {
return meta.activeMenu
}
return path
})
const activeMenu = computed(() => {
const { meta, path } = route
// if set path, the sidebar will highlight the path you set
if (meta.activeMenu) {
return meta.activeMenu
}
return path
})
//
const isCollapse = computed(()=>{
return !store.state.app.isCollapse
})
//
const isCollapse = computed(() => {
return !store.state.app.isCollapse
})
//
const mode = computed(()=>{
return store.state.setting.mode
})
//
const mode = computed(() => {
return store.state.setting.mode
})
</script>

View File

@ -1,58 +1,58 @@
<template>
<div ref="bsWrap" class="tags-scroll-wrap">
<div ref="bsContent" class="tags-scroll" >
<div ref="bsContent" class="tags-scroll">
<slot></slot>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, computed, watch, onMounted,nextTick } from 'vue';
import { useElementSize } from '@vueuse/core';
import BScroll from '@better-scroll/core';
import type { Options } from '@better-scroll/core';
import { ref, computed, watch, onMounted, nextTick } from 'vue'
import { useElementSize } from '@vueuse/core'
import BScroll from '@better-scroll/core'
import type { Options } from '@better-scroll/core'
interface Props {
/** better-scroll的配置: https://better-scroll.github.io/docs/zh-CN/guide/base-scroll-options.html */
options: Options;
}
const props = defineProps<Props>();
const bsWrap = ref<HTMLElement>();
const instance = ref<BScroll>();
const bsContent = ref<HTMLElement>();
function initBetterScroll() {
nextTick(()=>{
instance.value = new BScroll(bsWrap.value, props.options);
})
}
// BS
const { width: wrapWidth } = useElementSize(bsWrap);
const { width, height } = useElementSize(bsContent);
watch([() => wrapWidth.value, () => width.value, () => height.value], () => {
if (instance.value) {
instance.value.refresh();
interface Props {
/** better-scroll的配置: https://better-scroll.github.io/docs/zh-CN/guide/base-scroll-options.html */
options: Options
}
});
onMounted(() => {
initBetterScroll();
});
const props = defineProps<Props>()
defineExpose({ instance });
const bsWrap = ref<HTMLElement>()
const instance = ref<BScroll>()
const bsContent = ref<HTMLElement>()
function initBetterScroll() {
nextTick(() => {
instance.value = new BScroll(bsWrap.value, props.options)
})
}
// BS
const { width: wrapWidth } = useElementSize(bsWrap)
const { width, height } = useElementSize(bsContent)
watch([() => wrapWidth.value, () => width.value, () => height.value], () => {
if (instance.value) {
instance.value.refresh()
}
})
onMounted(() => {
initBetterScroll()
})
defineExpose({ instance })
</script>
<style scoped>
.tags-scroll-wrap{
width: 100%;
}
.tags-scroll-inner{
/*display: flex;*/
}
.tags-scroll{
display: inline-block;
}
.tags-scroll-wrap {
width: 100%;
}
.tags-scroll-inner {
/*display: flex;*/
}
.tags-scroll {
display: inline-block;
}
</style>

View File

@ -1,76 +1,72 @@
<template>
<div class="tags-wrap-container">
<div class="tags-view" ref="scrollContainer">
<better-scroll :options="{ scrollX: true, scrollY: false, }" ref="bsScroll">
<better-scroll :options="{ scrollX: true, scrollY: false }" ref="bsScroll">
<div class="tags-scroll-inner">
<div v-for="tag in visitedViews"
:ref="setTagRef"
:path= "tag.path"
:data-id="tag.path"
:fullPath="tag.fullPath"
:to="{ path: tag.path, query: tag.query, fullPath: tag.fullPath }"
:key="tag.path"
class="item-tag-wrap"
:class="isActive(tag)?'active':''"
@click="routerGo(tag)">
<div class="tags-view-item" >{{ tag.title }}</div>
<el-icon @click.prevent.stop="(e)=>closeSelectedTag(e,tag)" class="tag-icon">
<circle-close-filled /></el-icon>
<div
v-for="tag in visitedViews"
:ref="setTagRef"
:path="tag.path"
:data-id="tag.path"
:fullPath="tag.fullPath"
:to="{ path: tag.path, query: tag.query, fullPath: tag.fullPath }"
:key="tag.path"
class="item-tag-wrap"
:class="isActive(tag) ? 'active' : ''"
@click="routerGo(tag)"
>
<div class="tags-view-item">{{ tag.title }}</div>
<el-icon @click.prevent.stop="(e) => closeSelectedTag(e, tag)" class="tag-icon">
<circle-close-filled
/></el-icon>
</div>
</div>
</better-scroll>
</div>
<el-tooltip
class="box-item"
effect="dark"
content="点击刷新"
placement="bottom-end"
>
<el-tooltip class="box-item" effect="dark" content="点击刷新" placement="bottom-end">
<div class="refresh" @click="refresh">
<div class="refresh-inner">
<el-icon><Refresh />
</el-icon>
</div></div>
<el-icon><Refresh /> </el-icon> </div
></div>
</el-tooltip>
</div>
</template>
<script lang="ts" setup>
import {computed, nextTick, onMounted, reactive, ref, watch} from "vue";
import betterScroll from "./betterScroll.vue";
import { computed, nextTick, onMounted, reactive, ref, watch } from 'vue'
import betterScroll from './betterScroll.vue'
import { useStore } from 'vuex'
import {useRoute,useRouter} from 'vue-router'
import { useRoute, useRouter } from 'vue-router'
import path from 'path-browserify'
const store = useStore()
const route = useRoute()
const router = useRouter()
const refresh = ()=>{
const refresh = () => {
store.dispatch('app/setReload')
}
const routes = computed(()=>{
const routes = computed(() => {
return store.state.permission.routes
})
const visitedViews = computed(()=>{
const visitedViews = computed(() => {
return store.state.tagsView.visitedViews
})
const bsScroll = ref<Expose.BetterScroll>();
const bsScroll = ref<Expose.BetterScroll>()
let obj = new WeakMap()
let affixTags = ref([])
const tags = ref(new Map())
// ref tag
const setTagRef = (el)=>{
if(el){
if(!obj.get(el)){
tags.value.set(el.dataset['id'],el)
const setTagRef = (el) => {
if (el) {
if (!obj.get(el)) {
tags.value.set(el.dataset['id'], el)
}
obj.set(el,el)
obj.set(el, el)
}
}
@ -79,14 +75,14 @@
function filterAffixTags(routes, basePath = '/') {
let tags = []
routes.forEach(route => {
routes.forEach((route) => {
if (route.meta && route.meta.affix) {
const tagPath = path.resolve(basePath, route.path)
tags.push({
fullPath: tagPath,
path: tagPath,
name: route.name,
meta: { ...route.meta }
meta: { ...route.meta },
})
}
if (route.children) {
@ -99,9 +95,9 @@
return tags
}
const initTags = ()=>{
const initTags = () => {
let routesNew = routes.value
let affixTag = affixTags.value = filterAffixTags(routesNew)
let affixTag = (affixTags.value = filterAffixTags(routesNew))
for (const tag of affixTag) {
if (tag.name) {
store.dispatch('tagsView/addVisitedView', tag)
@ -109,15 +105,15 @@
}
}
const isActive = (rou)=> {
const isActive = (rou) => {
return rou.path === route.path
}
const isAffix = (tag)=>{
return tag.meta && tag.meta.affix
const isAffix = (tag) => {
return tag.meta && tag.meta.affix
}
const addTags = ()=> {
const addTags = () => {
const { name } = route
if(name==='Login'){
if (name === 'Login') {
return
}
if (name) {
@ -139,19 +135,18 @@
}
}
const closeSelectedTag = (event,view)=>{
if(tags.value.get(view.path)){
const closeSelectedTag = (event, view) => {
if (tags.value.get(view.path)) {
tags.value.delete(view.path)
}
store.dispatch('tagsView/delView', view).then(({ visitedViews }) => {
if (isActive(view)) {
toLastView(visitedViews, view)
}
})
}
const routerGo = (tag)=>{
const routerGo = (tag) => {
router.push({
path: tag.path,
query: tag.query,
@ -160,99 +155,98 @@
function handleScrollAction(currentTag) {
const scrollContainerRect = scrollContainer.value.getBoundingClientRect()
let { left:currx, width:currentWidth } = currentTag.getBoundingClientRect()
const clientX = currx + currentWidth / 2;
const currentX = clientX - scrollContainerRect.left;
const deltaX = currentX - scrollContainerRect.width / 2;
let { left: currx, width: currentWidth } = currentTag.getBoundingClientRect()
const clientX = currx + currentWidth / 2
const currentX = clientX - scrollContainerRect.left
const deltaX = currentX - scrollContainerRect.width / 2
if (bsScroll.value) {
const { maxScrollX, x: leftX } = bsScroll.value.instance;
const rightX = maxScrollX - leftX;
const update = deltaX > 0 ? Math.max(-deltaX, rightX) : Math.min(-deltaX, -leftX);
bsScroll.value?.instance.scrollBy(update, 0, 300);
const { maxScrollX, x: leftX } = bsScroll.value.instance
const rightX = maxScrollX - leftX
const update = deltaX > 0 ? Math.max(-deltaX, rightX) : Math.min(-deltaX, -leftX)
bsScroll.value?.instance.scrollBy(update, 0, 300)
}
}
function moveToCurrentTag(){
function moveToCurrentTag() {
nextTick(() => {
for (const [key, tag] of tags.value) {
let path = tag.attributes.path.value
if (path === route.path) {
let fullPath = tag.attributes.fullPath.value
//
handleScrollAction(tag,tags.value)
if (fullPath !== route.fullPath) {
store.dispatch('tagsView/updateVisitedView', route)
}
break
let path = tag.attributes.path.value
if (path === route.path) {
let fullPath = tag.attributes.fullPath.value
//
handleScrollAction(tag, tags.value)
if (fullPath !== route.fullPath) {
store.dispatch('tagsView/updateVisitedView', route)
}
break
}
}
})
}
onMounted(()=>{
onMounted(() => {
initTags()
addTags()
nextTick(()=>{
setTimeout(()=>{
nextTick(() => {
setTimeout(() => {
moveToCurrentTag()
},50)
}, 50)
})
watch(route,()=>{
watch(route, () => {
addTags()
nextTick(()=>{
setTimeout(()=>{
nextTick(() => {
setTimeout(() => {
moveToCurrentTag()
},100)
}, 100)
})
})
router.beforeEach(async (to, from, next)=>{
if((from.fullPath==='/error/404'||from.fullPath==='/error/401')&&to.fullPath==="/home") {
let whiteList = ['/error/404','/error/401']
router.beforeEach(async (to, from, next) => {
if (
(from.fullPath === '/error/404' || from.fullPath === '/error/401') &&
to.fullPath === '/home'
) {
let whiteList = ['/error/404', '/error/401']
await store.dispatch('tagsView/removeView', whiteList)
}
next()
})
})
</script>
<style lang="scss" scoped>
.tags-wrap-container{
display: flex;
justify-content: space-between;
align-items: center;
padding-left: 10px;
.tags-view{
background: white;
flex: 1;
box-sizing: border-box;
overflow: hidden;
}
.refresh{
//margin-left: 20px;
cursor: pointer;
font-size: 22px;
flex-shrink: 0;
.tags-wrap-container {
display: flex;
justify-content: space-between;
align-items: center;
justify-content: center;
.refresh-inner{
padding-left: 10px;
.tags-view {
background: white;
flex: 1;
box-sizing: border-box;
overflow: hidden;
}
.refresh {
//margin-left: 20px;
cursor: pointer;
font-size: 22px;
flex-shrink: 0;
display: flex;
align-items: center;
justify-content: center;
width: 50px;
height: 100%;
.refresh-inner {
display: flex;
align-items: center;
justify-content: center;
width: 50px;
height: 100%;
}
//box-shadow: 0 3px 6px -4px #0000001f, 0 6px 16px #00000014, 0 9px 28px 8px #0000000d;
}
//box-shadow: 0 3px 6px -4px #0000001f, 0 6px 16px #00000014, 0 9px 28px 8px #0000000d;
//padding-right: 10px;
}
//padding-right: 10px;
}
.item-tag-wrap{
.item-tag-wrap {
position: relative;
display: inline-flex;
align-items: center;
@ -261,7 +255,7 @@
cursor: pointer;
margin-right: 10px;
border: 1px solid #d8dce5;
&.active .tag-icon{
&.active .tag-icon {
display: block;
}
&.active {
@ -270,22 +264,22 @@
border-color: #42b983;
}
}
.item-tag-wrap:hover{
.item-tag-wrap:hover {
border-color: #42b983;
//color: #42b983;
}
.tags-scroll-inner{
.tags-scroll-inner {
display: flex;
flex-wrap: nowrap;
}
.tag-icon{
.tag-icon {
margin-left: 6px;
}
.tags-view-item {
position: relative;
z-index: 2;
white-space: nowrap;
.tags-inner{
.tags-inner {
display: flex;
align-items: center;
white-space: nowrap;

View File

@ -1,21 +1,17 @@
<template>
<el-dialog
v-model="dialogVisible"
title="修改密码"
width="60%"
>
<el-dialog v-model="dialogVisible" title="修改密码" width="60%">
<el-form
ref="ruleFormRef"
:model="ruleForm"
:rules="rules"
label-width="120px"
class="demo-ruleForm"
:size="formSize"
ref="ruleFormRef"
:model="ruleForm"
:rules="rules"
label-width="120px"
class="demo-ruleForm"
:size="formSize"
>
<el-form-item label="姓名" >
<el-form-item label="姓名">
<el-input v-model="ruleForm.name" disabled></el-input>
</el-form-item>
<el-form-item label="手机号码" >
<el-form-item label="手机号码">
<el-input v-model="ruleForm.mobile" disabled></el-input>
</el-form-item>
<el-form-item label="修改密码" prop="password">
@ -25,23 +21,21 @@
<template #footer>
<span class="dialog-footer">
<el-button @click="dialogVisible = false">取消</el-button>
<el-button type="primary" @click="submitForm(ruleFormRef)"
>确定</el-button
>
<el-button type="primary" @click="submitForm(ruleFormRef)">确定</el-button>
</span>
</template>
</el-dialog>
</template>
<script lang="ts" setup>
import { ref,defineExpose,reactive, } from 'vue'
import { ref, defineExpose, reactive } from 'vue'
import { ElMessageBox } from 'element-plus'
import type { ElForm } from 'element-plus'
const dialogVisible = ref(false)
const show = ()=>{
const show = () => {
dialogVisible.value = true
}
const hide = ()=>{
const hide = () => {
dialogVisible.value = false
}
type FormInstance = InstanceType<typeof ElForm>
@ -85,7 +79,7 @@
</script>
<style scoped>
.dialog-footer button:first-child {
margin-right: 10px;
}
.dialog-footer button:first-child {
margin-right: 10px;
}
</style>

View File

@ -1,24 +1,30 @@
<template>
<div
class="m-layout-header"
:style="{left:`${mode==='horizontal'?0:isCollapse?'56':'210'}px`}">
<div class="header" :class="{
transverseMenu:mode==='horizontal'
}">
<menu-slide v-if="mode==='horizontal'"/>
<div class="left" v-if="mode==='vertical'">
class="m-layout-header"
:style="{ left: `${mode === 'horizontal' ? 0 : isCollapse ? '56' : '210'}px` }"
>
<div
class="header"
:class="{
transverseMenu: mode === 'horizontal',
}"
>
<menu-slide v-if="mode === 'horizontal'" />
<div class="left" v-if="mode === 'vertical'">
<div>
<el-icon class="icon" v-if="isCollapse" @click="handleCollapse"><expand /></el-icon>
<el-icon class="icon" v-else @click="handleCollapse"><fold/></el-icon>
<el-icon class="icon" v-else @click="handleCollapse"><fold /></el-icon>
</div>
<u-hamburger/>
<u-hamburger />
</div>
<div class="right">
<u-info/>
<u-screen-full/>
<u-info />
<u-screen-full />
<el-dropdown @command="commandAction">
<span class="el-dropdown-link">
<el-avatar :icon="UserFilled" :size="30" style="margin-right: 6px"/>{{ userInfo.username }}
<el-avatar :icon="UserFilled" :size="30" style="margin-right: 6px" />{{
userInfo.username
}}
<el-icon class="el-icon--right">
<arrow-down />
</el-icon>
@ -32,8 +38,8 @@
</el-dropdown>
</div>
</div>
<tag-views v-if="isShowTag"/>
<personal ref="person"/>
<tag-views v-if="isShowTag" />
<personal ref="person" />
</div>
</template>
@ -41,68 +47,59 @@
import { UserFilled } from '@element-plus/icons-vue'
import Personal from './Personal.vue'
import TagViews from '../TagsView/index.vue'
import UHamburger from "@/components/u-Hamburger/index.vue"
import UHamburger from '@/components/u-Hamburger/index.vue'
import UScreenFull from '@/components/u-screenfull/index.vue'
import UInfo from '@/components/u-info/index.vue'
import MenuSlide from '../Sidebar/menuSlide.vue'
import {computed, ref,} from 'vue'
import {useRouter} from 'vue-router'
import { computed, ref } from 'vue'
import { useRouter } from 'vue-router'
import { ElMessageBox, ElMessage } from 'element-plus'
import {useStore} from "vuex";
import { useStore } from 'vuex'
const store = useStore()
const person = ref()
const router = useRouter()
const isCollapse = computed(()=>{
const isCollapse = computed(() => {
return !store.state.app.isCollapse
})
const mode = computed(()=>{
const mode = computed(() => {
return store.state.setting.mode
})
const isShowTag = computed(()=>{
const isShowTag = computed(() => {
return store.state.setting.isShowTag
})
const userInfo = computed(()=>{
const userInfo = computed(() => {
return store.state.user.userInfo
})
const logOut = async ()=>{
ElMessageBox.confirm(
'确定退出登录吗?',
'退出登录',
{
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
}
)
.then(async () => {
try {
await store.dispatch('user/logout')
router.push({path:'/login'})
store.dispatch('permission/clearRoutes')
store.dispatch('tagsView/clearVisitedView')
}catch (e) {
}
})
.catch(() => {
})
const logOut = async () => {
ElMessageBox.confirm('确定退出登录吗?', '退出登录', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
})
.then(async () => {
try {
await store.dispatch('user/logout')
router.push({ path: '/login' })
store.dispatch('permission/clearRoutes')
store.dispatch('tagsView/clearVisitedView')
} catch (e) {}
})
.catch(() => {})
}
const commandAction = (key:number)=>{
switch (key){
const commandAction = (key: number) => {
switch (key) {
case 1:
logOut()
break;
break
case 2:
person.value.show()
break;
break
}
}
const handleCollapse = () => {
@ -111,16 +108,16 @@
</script>
<style lang="scss" scoped>
.mobile{
.m-layout-header{
left: 0!important;
.mobile {
.m-layout-header {
left: 0 !important;
}
}
}
.icon{
font-size:24px;
.icon {
font-size: 24px;
cursor: pointer;
}
.header{
.header {
height: 60px;
width: 100%;
display: flex;
@ -128,21 +125,21 @@
padding: 0 10px;
box-sizing: border-box;
justify-content: space-between;
.left{
.left {
display: flex;
align-items: center;
}
.right{
.right {
display: flex;
align-items: center;
}
}
.m-layout-header{
.m-layout-header {
position: fixed;
top: 0;
background: white;
left: 0;
z-index:99;
z-index: 99;
right: 0;
transition: left 0.28s;
flex-shrink: 0;
@ -150,7 +147,7 @@
box-shadow: 0 1px 4px rgb(0 21 41 / 8%);
}
.el-dropdown{
.el-dropdown {
display: flex;
height: 100%;
align-items: center;
@ -161,5 +158,4 @@
display: flex;
align-items: center;
}
</style>

View File

@ -1,26 +1,29 @@
<template>
<div class="g-container-layout" :class="classObj" >
<div v-if="device==='mobile'&&!isCollapse" class="drawer-bg" @click="handleClickOutside" />
<sidebar class="sidebar-container" v-if="mode==='vertical'"/>
<div class="main-container" :class="{
hideSliderLayout:mode==='horizontal'
}">
<div class="g-container-layout" :class="classObj">
<div v-if="device === 'mobile' && !isCollapse" class="drawer-bg" @click="handleClickOutside" />
<sidebar class="sidebar-container" v-if="mode === 'vertical'" />
<div
class="main-container"
:class="{
hideSliderLayout: mode === 'horizontal',
}"
>
<u-header />
<div class="m-container-content" :class="{'app-main-hide-tag':!isShowTag}">
<app-main/>
<div class="m-container-content" :class="{ 'app-main-hide-tag': !isShowTag }">
<app-main />
</div>
</div>
</div>
</template>
<script lang="ts">
import {computed, defineComponent, ref} from 'vue';
import { computed, defineComponent, ref } from 'vue'
import Sidebar from './components/Sidebar/index.vue'
import UHeader from './components/UHeader/index.vue'
import AppMain from './components/AppMain.vue'
import {useResizeHandler} from './hooks/useResizeHandler'
import { useResizeHandler } from './hooks/useResizeHandler'
import {useStore} from "vuex";
import { useStore } from 'vuex'
export default defineComponent({
name: 'layout',
@ -29,62 +32,62 @@
UHeader,
AppMain,
},
setup(){
setup() {
const store = useStore()
//
const isCollapse = computed(()=>{
const isCollapse = computed(() => {
return !store.state.app.isCollapse
})
let {device} = useResizeHandler()
let { device } = useResizeHandler()
const classObj = computed(()=>{
const classObj = computed(() => {
return {
hideSidebar:!store.state.app.isCollapse,
hideSidebar: !store.state.app.isCollapse,
openSidebar: store.state.app.isCollapse,
withoutAnimation: store.state.app.withoutAnimation,
mobile: device.value === 'mobile'
mobile: device.value === 'mobile',
}
})
const handleClickOutside = ()=> {
const handleClickOutside = () => {
store.dispatch('app/closeSideBar', { withoutAnimation: false })
}
const isShowTag = computed(()=>{
const isShowTag = computed(() => {
return store.state.setting.isShowTag
})
const mode = computed(()=>{
const mode = computed(() => {
return store.state.setting.mode
})
return{
return {
isCollapse,
device,
classObj,
isShowTag,
mode,
handleClickOutside
handleClickOutside,
}
}
});
},
})
</script>
<style lang="scss" scoped>
.g-container-layout{
.g-container-layout {
//display: flex;
height: 100%;
width: 100%;
.main-container{
.main-container {
//overflow: auto;
display: flex;
flex: 1;
box-sizing: border-box;
flex-direction: column
flex-direction: column;
}
&.mobile.openSidebar {
position: fixed;
top: 0;
}
}
.sidebar-container{
.sidebar-container {
display: flex;
flex-direction: column;
}
@ -97,7 +100,7 @@
position: absolute;
z-index: 999;
}
.m-container-content{
.m-container-content {
//padding: 20px;
/*background: #f6f8f9;*/
padding-top: 93px;
@ -105,7 +108,7 @@
height: 100vh;
position: relative;
}
.app-main-hide-tag{
.app-main-hide-tag {
padding-top: 80px;
}
</style>

View File

@ -1,3 +1,3 @@
@import './variables.scss';
@import './sidebar.scss';
@import "./transition.scss";
@import './transition.scss';

View File

@ -1,19 +1,18 @@
#app {
.main-container {
min-height: 100%;
transition: margin-left .28s;
transition: margin-left 0.28s;
margin-left: $sideBarWidth;
position: relative;
}
.hideSliderLayout{
.hideSliderLayout {
margin-left: 0;
.el-menu--horizontal{
.el-menu--horizontal {
border-bottom: none;
}
}
.transverseMenu{
.transverseMenu {
background-color: $menuBg;
}
@ -86,11 +85,11 @@
}
}
.is-active>.el-sub-menu__title {
.is-active > .el-sub-menu__title {
color: $subMenuActiveText !important;
}
& .nest-menu .el-sub-menu>.el-sub-menu__title,
& .nest-menu .el-sub-menu > .el-sub-menu__title,
& .el-sub-menu .el-menu-item {
min-width: $sideBarWidth !important;
background-color: $subMenuBg !important;
@ -130,7 +129,7 @@
.el-submenu {
overflow: hidden;
&>.el-submenu__title {
& > .el-submenu__title {
padding: 0 !important;
.svg-icon {
@ -149,8 +148,8 @@
.el-menu--collapse {
.el-sub-menu {
&>.el-sub-menu__title {
&>span {
& > .el-sub-menu__title {
& > span {
height: 0;
width: 0;
overflow: hidden;
@ -173,7 +172,7 @@
}
.sidebar-container {
transition: transform .28s;
transition: transform 0.28s;
width: $sideBarWidth !important;
}
@ -187,7 +186,6 @@
}
.withoutAnimation {
.main-container,
.sidebar-container {
transition: none;
@ -197,7 +195,7 @@
// when menu collapsed
.el-menu--vertical {
&>.el-menu {
& > .el-menu {
.svg-icon {
margin-right: 16px;
}
@ -207,7 +205,7 @@
}
}
.nest-menu .el-sub-menu>.el-sub-menu__title,
.nest-menu .el-sub-menu > .el-sub-menu__title,
.el-menu-item {
&:hover {
// you can use $subMenuHover
@ -216,7 +214,7 @@
}
// the scroll bar appears when the subMenu is too long
>.el-menu--popup {
> .el-menu--popup {
max-height: 100vh;
overflow-y: auto;

View File

@ -27,7 +27,6 @@
transform: translateX(20px);
}
// 面包屑动画
.breadcrumb-enter-active {
transition: all 0.25s;
@ -38,8 +37,6 @@
transform: translateX(30px) skewX(-50deg);
}
.fade-transform-leave-active,
.fade-transform-enter-active {
transition: all 0.2s cubic-bezier(0.645, 0.045, 0.355, 1), border 0s;

View File

@ -1,23 +1,23 @@
// base color
$blue:#324157;
$light-blue:#3A71A8;
$red:#C03639;
$pink: #E65D6E;
$green: #30B08F;
$tiffany: #4AB7BD;
$yellow:#FEC171;
$panGreen: #30B08F;
$blue: #324157;
$light-blue: #3a71a8;
$red: #c03639;
$pink: #e65d6e;
$green: #30b08f;
$tiffany: #4ab7bd;
$yellow: #fec171;
$panGreen: #30b08f;
// sidebar
$menuText:#bfcbd9;
$menuActiveText:#409EFF;
$subMenuActiveText:#f4f4f5; // https://github.com/ElemeFE/element/issues/12951
$menuText: #bfcbd9;
$menuActiveText: #409eff;
$subMenuActiveText: #f4f4f5; // https://github.com/ElemeFE/element/issues/12951
$menuBg:#304156;
$menuHover:#263445;
$menuBg: #304156;
$menuHover: #263445;
$subMenuBg:#1f2d3d;
$subMenuHover:#001528;
$subMenuBg: #1f2d3d;
$subMenuHover: #001528;
$sideBarWidth: 210px;

View File

@ -1,4 +1,3 @@
const TokenKey = 'zb-token'
export function getToken() {
@ -6,9 +5,9 @@ export function getToken() {
}
export function setToken(token) {
return localStorage.TokenKey = token
return (localStorage.TokenKey = token)
}
export function removeToken() {
return localStorage.TokenKey =''
return (localStorage.TokenKey = '')
}

View File

@ -88,7 +88,7 @@ export async function downloadFiles2ZipWithFolder(params: IDownloadFiles2ZipWith
async function handleFolder(zip: JsZip, folder: IFolder) {
console.log({folder})
let folderPromises: Promise<any>[] = [];
const folderPromises: Promise<any>[] = [];
const promises = folder?.files?.map(async param => await handleEachFile(param, zip, folder.folderName));
await Promise.all([...promises, ...folderPromises]);
}
@ -169,7 +169,7 @@ function handleDataWithRender(worksheet: Worksheet, sheet: ISheet) {
// @ts-ignore
function getValueFromRender(renderResult: any) {
if (renderResult?.type) {
let children = renderResult?.props?.children;
const children = renderResult?.props?.children;
if (children?.type) {
return getValueFromRender(children);
} else {

View File

@ -1,12 +1,35 @@
export default {
imgs: ['爱你',
'爱情', '爱心', '傲慢',
'白眼', '抱拳', '鄙视',
'闭嘴', '便便', '擦汗',
'菜刀', '差劲', '呲牙',
'大哭', '蛋糕', '刀',
'得意', '凋谢', '发呆', 'NO', 'OK',
'发抖', '发怒', '饭', '飞吻', '奋斗',
'疯了', '尴尬', '勾引', '鼓掌', '哈欠',
]
imgs: [
'爱你',
'爱情',
'爱心',
'傲慢',
'白眼',
'抱拳',
'鄙视',
'闭嘴',
'便便',
'擦汗',
'菜刀',
'差劲',
'呲牙',
'大哭',
'蛋糕',
'刀',
'得意',
'凋谢',
'发呆',
'NO',
'OK',
'发抖',
'发怒',
'饭',
'飞吻',
'奋斗',
'疯了',
'尴尬',
'勾引',
'鼓掌',
'哈欠',
],
}

View File

@ -21,15 +21,15 @@ export const exportExcel = async ({column,data,filename,autoWidth,format})=>{
// 创建工作表
const worksheet = workbook.addWorksheet(filename);
// 设置列名
let columnsName = [];
const columnsName = [];
column.forEach((item,index)=>{
let obj = {
const obj = {
header: item.label, key:item.name, width: null
}
if(autoWidth){
let maxArr = [autoWidthAction(item.label)]
const maxArr = [autoWidthAction(item.label)]
data.forEach(ite=>{
let str = ite[item.name] ||''
const str = ite[item.name] ||''
if(str){
maxArr.push(autoWidthAction(str))
}
@ -93,15 +93,15 @@ export const exportStyleExcel =async ({column,data,filename,autoWidth,format})=>
// 创建工作表
const worksheet = workbook.addWorksheet(filename);
// 设置列名
let columnsName = [];
const columnsName = [];
column.forEach((item,index)=>{
let obj = {
const obj = {
header: item.label, key:item.name, width: null
}
if(autoWidth){
let maxArr = [autoWidthAction(item.label)]
const maxArr = [autoWidthAction(item.label)]
data.forEach(ite=>{
let str = ite[item.name] ||''
const str = ite[item.name] ||''
if(str){
maxArr.push(autoWidthAction(str))
}
@ -161,7 +161,7 @@ export const exportMultiHeaderExcel = ({column,data,filename,autoWidth})=>{
// 创建excel
const workbook = new ExcelJS.Workbook();
// 创建工作表
let sheet = workbook.addWorksheet("sheet1");
const sheet = workbook.addWorksheet("sheet1");
// 添加表头
sheet.getRow(1).values = ["序号", "日期","地址" ,"配送消息" ,,, ];
@ -173,16 +173,16 @@ export const exportMultiHeaderExcel = ({column,data,filename,autoWidth})=>{
"城市",
"邮编"
];
let headers = [];
const headers = [];
column.forEach((item,index)=>{
if(item.children){
item.children.forEach(itemChild=>{
let obj = {
const obj = {
key:itemChild.name, width: null
}
let maxArr = [autoWidthAction(itemChild.label)]
const maxArr = [autoWidthAction(itemChild.label)]
data.forEach(ite=>{
let str = ite[itemChild.name] ||''
const str = ite[itemChild.name] ||''
if(str){
maxArr.push(autoWidthAction(str))
}
@ -193,12 +193,12 @@ export const exportMultiHeaderExcel = ({column,data,filename,autoWidth})=>{
})
}else {
let obj = {
const obj = {
key:item.name, width: null
}
let maxArr = [autoWidthAction(item.label)]
const maxArr = [autoWidthAction(item.label)]
data.forEach(ite=>{
let str = ite[item.name] ||''
const str = ite[item.name] ||''
if(str){
maxArr.push(autoWidthAction(str))
}

View File

@ -17,8 +17,8 @@ export function parseTime(time, cFormat) {
if (typeof time === 'object') {
date = time
} else {
if ((typeof time === 'string')) {
if ((/^[0-9]+$/.test(time))) {
if (typeof time === 'string') {
if (/^[0-9]+$/.test(time)) {
// support "1548221490638"
time = parseInt(time)
} else {
@ -28,7 +28,7 @@ export function parseTime(time, cFormat) {
}
}
if ((typeof time === 'number') && (time.toString().length === 10)) {
if (typeof time === 'number' && time.toString().length === 10) {
time = time * 1000
}
date = new Date(time)
@ -40,12 +40,14 @@ export function parseTime(time, cFormat) {
h: date.getHours(),
i: date.getMinutes(),
s: date.getSeconds(),
a: date.getDay()
a: date.getDay(),
}
const time_str = format.replace(/{([ymdhisa])+}/g, (result, key) => {
const value = formatObj[key]
// Note: getDay() returns 0 on Sunday
if (key === 'a') { return ['日', '一', '二', '三', '四', '五', '六'][value ] }
if (key === 'a') {
return ['日', '一', '二', '三', '四', '五', '六'][value]
}
return value.toString().padStart(2, '0')
})
return time_str
@ -81,15 +83,7 @@ export function formatTime(time, option) {
return parseTime(time, option)
} else {
return (
d.getMonth() +
1 +
'月' +
d.getDate() +
'日' +
d.getHours() +
'时' +
d.getMinutes() +
'分'
d.getMonth() + 1 + '月' + d.getDate() + '日' + d.getHours() + '时' + d.getMinutes() + '分'
)
}
}
@ -124,7 +118,7 @@ export function byteLength(str) {
const code = str.charCodeAt(i)
if (code > 0x7f && code <= 0x7ff) s++
else if (code > 0x7ff && code <= 0xffff) s += 2
if (code >= 0xDC00 && code <= 0xDFFF) i--
if (code >= 0xdc00 && code <= 0xdfff) i--
}
return s
}
@ -150,10 +144,10 @@ export function cleanArray(actual) {
export function param(json) {
if (!json) return ''
return cleanArray(
Object.keys(json).map(key => {
Object.keys(json).map((key) => {
if (json[key] === undefined) return ''
return encodeURIComponent(key) + '=' + encodeURIComponent(json[key])
})
}),
).join('&')
}
@ -168,7 +162,7 @@ export function param2Obj(url) {
}
const obj = {}
const searchArr = search.split('&')
searchArr.forEach(v => {
searchArr.forEach((v) => {
const index = v.indexOf('=')
if (index !== -1) {
const name = v.substring(0, index)
@ -202,7 +196,7 @@ export function objectMerge(target, source) {
if (Array.isArray(source)) {
return source.slice()
}
Object.keys(source).forEach(property => {
Object.keys(source).forEach((property) => {
const sourceProperty = source[property]
if (typeof sourceProperty === 'object') {
target[property] = objectMerge(target[property], sourceProperty)
@ -227,8 +221,7 @@ export function toggleClass(element, className) {
classString += '' + className
} else {
classString =
classString.substr(0, nameIndex) +
classString.substr(nameIndex + className.length)
classString.substr(0, nameIndex) + classString.substr(nameIndex + className.length)
}
element.className = classString
}
@ -254,7 +247,7 @@ export function getTime(type) {
export function debounce(func, wait, immediate) {
let timeout, args, context, timestamp, result
const later = function() {
const later = function () {
// 据上一次触发时间间隔
const last = +new Date() - timestamp
@ -271,7 +264,7 @@ export function debounce(func, wait, immediate) {
}
}
return function(...args) {
return function (...args) {
context = this
timestamp = +new Date()
const callNow = immediate && !timeout
@ -298,7 +291,7 @@ export function deepClone(source) {
throw new Error('error arguments', 'deepClone')
}
const targetObj = source.constructor === Array ? [] : {}
Object.keys(source).forEach(keys => {
Object.keys(source).forEach((keys) => {
if (source[keys] && typeof source[keys] === 'object') {
targetObj[keys] = deepClone(source[keys])
} else {
@ -356,70 +349,77 @@ export function removeClass(ele, cls) {
}
}
export function getColor() {
var str = '#';
var arr = ['1', '2', '3', '4', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'];
var str = '#'
var arr = ['1', '2', '3', '4', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f']
for (var i = 0; i < 6; i++) {
var num = parseInt(Math.random() * 16);
str += arr[num];
var num = parseInt(Math.random() * 16)
str += arr[num]
}
return str;
return str
}
// 检查给定的值是否是数组
export const isArray = function(value) {
return objToString.call(value) === "[object Array]";
};
var funProto = Function.prototype;
var objProto = Object.prototype;
export const isArray = function (value) {
return objToString.call(value) === '[object Array]'
}
var funProto = Function.prototype
var objProto = Object.prototype
var getPrototypeOf = Object.getPrototypeOf;
var getPrototypeOf = Object.getPrototypeOf
var objToString = objProto.toString;
var hasOwnProperty = objProto.hasOwnProperty;
var funToString = funProto.toString;
var objToString = objProto.toString
var hasOwnProperty = objProto.hasOwnProperty
var funToString = funProto.toString
// 检查给定的值是否是字符串
export const isString = function(value) {
return objToString.call(value) === "[object String]";
};
export const isString = function (value) {
return objToString.call(value) === '[object String]'
}
// 检查给定的值是否是纯对象,纯对象是指通过 {} 或 new Object() 声明的对象
export const isPlainObject = function(value) {
if (!value || objToString.call(value) !== "[object Object]") {
return false;
export const isPlainObject = function (value) {
if (!value || objToString.call(value) !== '[object Object]') {
return false
}
var prototype = getPrototypeOf(value);
var prototype = getPrototypeOf(value)
if (prototype === null) {
return true;
return true
}
var constructor = hasOwnProperty.call(prototype, "constructor") && prototype.constructor;
var constructor = hasOwnProperty.call(prototype, 'constructor') && prototype.constructor
return typeof constructor === "function" && funToString.call(constructor) === funToString.call(Object);
};
return (
typeof constructor === 'function' && funToString.call(constructor) === funToString.call(Object)
)
}
// // 深度克隆 array 数组或 json 对象,返回克隆后的副本
export const deepObjClone = function(obj){
export const deepObjClone = function (obj) {
let weakMap = new WeakMap()
function clone (obj){
if(obj==null){return obj}
if(obj instanceof Date){ return new Date(obj) }
if(obj instanceof RegExp){ return new RegExp(obj)}
if(typeof obj !== 'object') return obj
function clone(obj) {
if (obj == null) {
return obj
}
if (obj instanceof Date) {
return new Date(obj)
}
if (obj instanceof RegExp) {
return new RegExp(obj)
}
if (typeof obj !== 'object') return obj
if(weakMap.get(obj)){
if (weakMap.get(obj)) {
return weakMap.get(obj)
}
var copy = new obj.constructor
weakMap.set(obj,copy)
for(var key in obj){
if(Object.prototype.hasOwnProperty.call(obj, key)){
var value = obj[key];
copy[key] = clone(value);
var copy = new obj.constructor()
weakMap.set(obj, copy)
for (var key in obj) {
if (Object.prototype.hasOwnProperty.call(obj, key)) {
var value = obj[key]
copy[key] = clone(value)
}
}
return copy;
return copy
}
return clone (obj)
};
return clone(obj)
}

View File

@ -24,7 +24,8 @@ export function validUsername(str) {
* @returns {Boolean}
*/
export function validURL(url) {
const reg = /^(https?|ftp):\/\/([a-zA-Z0-9.-]+(:[a-zA-Z0-9.&%$-]+)*@)*((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}|([a-zA-Z0-9-]+\.)*[a-zA-Z0-9-]+\.(com|edu|gov|int|mil|net|org|biz|arpa|info|name|pro|aero|coop|museum|[a-zA-Z]{2}))(:[0-9]+)*(\/($|[a-zA-Z0-9.,?'\\+&%$#=~_-]+))*$/
const reg =
/^(https?|ftp):\/\/([a-zA-Z0-9.-]+(:[a-zA-Z0-9.&%$-]+)*@)*((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}|([a-zA-Z0-9-]+\.)*[a-zA-Z0-9-]+\.(com|edu|gov|int|mil|net|org|biz|arpa|info|name|pro|aero|coop|museum|[a-zA-Z]{2}))(:[0-9]+)*(\/($|[a-zA-Z0-9.,?'\\+&%$#=~_-]+))*$/
return reg.test(url)
}
@ -60,7 +61,8 @@ export function validAlphabets(str) {
* @returns {Boolean}
*/
export function validEmail(email) {
const reg = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
const reg =
/^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
return reg.test(email)
}

View File

@ -1,18 +1,18 @@
<template>
<div class="home">
<img alt="Vue logo" src="../assets/logo.png">
<HelloWorld msg="Welcome to Your Vue.js + TypeScript App"/>
<img alt="Vue logo" src="../assets/logo.png" />
<HelloWorld msg="Welcome to Your Vue.js + TypeScript App" />
</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import HelloWorld from '@/components/HelloWorld.vue'; // @ is an alias to /src
import { defineComponent } from 'vue'
import HelloWorld from '@/components/HelloWorld.vue' // @ is an alias to /src
export default defineComponent({
name: 'Home',
components: {
HelloWorld,
},
});
export default defineComponent({
name: 'Home',
components: {
HelloWorld,
},
})
</script>

View File

@ -1,198 +1,208 @@
<template>
<div class="m-animation" ref="mAnimation">
<div class="item-animation">
<div class="item">
<div class="item-icon item-icon1">
<img src="@/assets/image/circle-bg.png" class="circle-bg"/>
</div>
<div class="item-right">
<div class="item-right-inner">
<div class="text-title">带动就业人数</div>
<div class="text-number"><count-to :startVal="0" :endVal="6285" :duration="4000" separator=""></count-to></div>
<div class="text-der text-decenter-wrapr">
<span class="left">同比去年</span>
<img src="@/assets/image/allow.png"/>
<span class="right">+78%</span>
</div>
<div class="item-animation">
<div class="item">
<div class="item-icon item-icon1">
<img src="@/assets/image/circle-bg.png" class="circle-bg" />
</div>
<div class="item-right">
<div class="item-right-inner">
<div class="text-title">带动就业人数</div>
<div class="text-number"
><count-to :startVal="0" :endVal="6285" :duration="4000" separator=""></count-to
></div>
<div class="text-der text-decenter-wrapr">
<span class="left">同比去年</span>
<img src="@/assets/image/allow.png" />
<span class="right">+78%</span>
</div>
</div>
</div>
</div>
<div>
<div class="circle-dot" v-for="item,index in pointStyle" :key="index" :style="{
left:`${item.left}px`,
top:`${item.top}px`
}"></div>
</div>
</div>
<div>
<div
class="circle-dot"
v-for="(item, index) in pointStyle"
:key="index"
:style="{
left: `${item.left}px`,
top: `${item.top}px`,
}"
></div>
</div>
</div>
</template>
<script setup lang="ts">
import CountTo from '@/components/u-count-to/vue-countTo.vue'
import { nextTick, onMounted, ref } from 'vue'
import CountTo from '@/components/u-count-to/vue-countTo.vue'
import { nextTick, onMounted, ref } from 'vue'
const mAnimation = ref<HTMLElement|null>()
const pointStyle = ref([])
const mAnimation = ref<HTMLElement | null>()
const pointStyle = ref([])
function randomNum (minNum, maxNum) {
switch (arguments.length) {
case 1:
return parseInt(Math.random() * minNum + 1)
case 2:
return parseInt(Math.random() * (maxNum - minNum + 1) + minNum)
default:
return 0
function randomNum(minNum, maxNum) {
switch (arguments.length) {
case 1:
return parseInt(Math.random() * minNum + 1)
case 2:
return parseInt(Math.random() * (maxNum - minNum + 1) + minNum)
default:
return 0
}
}
}
const getAttribute = () => {
const mAnimationInfo = mAnimation.value.getBoundingClientRect()
const obj = []
for (let i = 0; i < 30; i++) {
if (!obj[i]) { obj[i] = {} }
obj[i].left = randomNum(0, mAnimationInfo.width)
const getAttribute = () => {
const mAnimationInfo = mAnimation.value.getBoundingClientRect()
const obj = []
for (let i = 0; i < 30; i++) {
if (!obj[i]) {
obj[i] = {}
}
obj[i].left = randomNum(0, mAnimationInfo.width)
}
for (let i = 0; i < 30; i++) {
if (!obj[i]) {
obj[i] = {}
}
obj[i].top = randomNum(0, mAnimationInfo.height)
}
return obj
}
for (let i = 0; i < 30; i++) {
if (!obj[i]) { obj[i] = {} }
obj[i].top = randomNum(0, mAnimationInfo.height)
}
return obj
}
onMounted(() => {
nextTick(() => {
pointStyle.value = getAttribute()
console.log('pointStyle',pointStyle)
onMounted(() => {
nextTick(() => {
pointStyle.value = getAttribute()
console.log('pointStyle', pointStyle)
})
})
})
</script>
<style lang="scss" scoped>
.m-animation{
height: 100%;
width: 100%;
background-color: #030409;
box-sizing: border-box;
position: relative;
.circle-bg{
animation:rotate 5s infinite linear;
}
@keyframes rotate{
0%{transform:rotate(0deg);}
100%{transform:rotate(360deg);}
}
.item {
.m-animation {
height: 100%;
width: 100%;
background-color: #030409;
box-sizing: border-box;
position: relative;
.circle-bg {
animation: rotate 5s infinite linear;
}
@keyframes rotate {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
.item {
display: flex;
/*align-items: center;*/
.item-icon {
width: 117px;
height: 109px;
}
.item-icon1 {
background: url('../../assets/image/center-inner1.png') no-repeat center 43%;
}
.item-right {
margin-left: 20px;
.item-right-inner {
height: 100%;
display: flex;
flex-direction: column;
justify-content: space-between;
}
.text-title {
font-size: 20px;
letter-spacing: 1px;
color: #ffffff;
/*margin-bottom: 6px;*/
/*height: 20px;*/
}
.text-number {
font-size: 44px;
letter-spacing: 2px;
color: #00e4ff;
}
.text-der {
overflow: hidden;
box-sizing: border-box;
display: flex;
font-size: 16px;
color: #ffffff;
letter-spacing: 1px;
.left {
margin-right: 10px;
}
img {
margin-right: 4px;
margin-top: 4px;
width: 11px;
height: 15px;
}
.right {
color: #ff0000;
}
}
}
}
display: flex;
/*align-items: center;*/
.item-icon {
width: 117px;
height: 109px;
}
.item-icon1{
background: url("../../assets/image/center-inner1.png") no-repeat center 43%;
}
.item-right{
margin-left: 20px;
.item-right-inner{
.circle-dot {
width: 5px;
height: 5px;
border-radius: 50%;
background: yellow;
text-align: center;
font-weight: bold;
position: absolute;
/*line-height: 100px;*/
z-index: 1;
&::before {
background: inherit;
content: '';
position: absolute;
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
justify-content: space-between;
left: 0;
top: 0;
z-index: -2;
border-radius: 50%;
animation: twinkling 2.2s ease-in-out infinite;
}
.text-title{
font-size: 20px;
letter-spacing: 1px;
color: #ffffff;
/*margin-bottom: 6px;*/
/*height: 20px;*/
}
.text-number{
font-size: 44px;
letter-spacing: 2px;
color: #00e4ff;
}
.text-der{
overflow: hidden;
box-sizing: border-box;
display: flex;
font-size: 16px;
color: #ffffff;
letter-spacing: 1px;
.left{
margin-right: 10px;
}
img{
margin-right: 4px;
margin-top: 4px;
width: 11px;
height: 15px;
}
.right{
color: #ff0000;
}
&::after {
background: inherit;
content: '';
position: absolute;
width: 130%;
height: 130%;
left: -15%;
top: -15%;
z-index: -1;
border-radius: 50%;
animation: twinkling 2.2s ease-in-out infinite;
}
}
}
@keyframes twinkling {
0% {
opacity: 0.2;
filter: alpha(opacity=20);
transform: scale(1);
}
50% {
opacity: 0.5;
filter: alpha(opacity=50);
transform: scale(1.4);
}
.circle-dot {
width: 5px;
height: 5px;
border-radius: 50%;
background: yellow;
text-align: center;
font-weight: bold;
position: absolute;
/*line-height: 100px;*/
z-index: 1;
&::before {
background: inherit;
content: '';
position: absolute;
width: 100%;
height: 100%;
left: 0;
top: 0;
z-index: -2;
border-radius: 50%;
animation: twinkling 2.2s ease-in-out infinite;
100% {
opacity: 0.2;
filter: alpha(opacity=20);
transform: scale(0.7);
}
}
&::after {
background: inherit;
content: '';
position: absolute;
width: 130%;
height: 130%;
left: -15%;
top: -15%;
z-index: -1;
border-radius: 50%;
animation: twinkling 2.2s ease-in-out infinite;
.item-animation {
padding: 20px;
}
}
@keyframes twinkling {
0% {
opacity: 0.2;
filter: alpha(opacity=20);
transform: scale(1);
}
50% {
opacity: 0.5;
filter: alpha(opacity=50);
transform: scale(1.4);
}
100% {
opacity: 0.2;
filter: alpha(opacity=20);
transform: scale(0.7);
}
}
.item-animation{
padding: 20px;
}
}
</style>

View File

@ -12,22 +12,21 @@
</div>
</template>
<script setup lang="ts">
import LineCharts from './components/complex/line/index.vue'
import BarCharts from './components/complex/bar/index.vue'
import LineCharts from './components/complex/line/index.vue'
import BarCharts from './components/complex/bar/index.vue'
</script>
<style lang="scss" scoped>
.m-complex{
.m-complex {
height: 100%;
width: 100%;
background-color: #030409;
.m-complex-inner{
.m-complex-inner {
padding: 20px;
display: flex;
flex-wrap: wrap;
}
}
.item-complex{
.item-complex {
width: 454px;
height: 292px;
background-image: url('../../assets/image/charts/1-1-bg.png');
@ -35,5 +34,4 @@ import BarCharts from './components/complex/bar/index.vue'
background-size: contain;
background-repeat: no-repeat;
}
</style>

View File

@ -1,35 +1,35 @@
<template>
<div :id="id" :class="className" :style="{height:height,width:width}" />
<div :id="id" :class="className" :style="{ height: height, width: width }" />
</template>
<script lang="ts" setup>
import 'echarts-liquidfill/src/liquidFill.js'
import * as echarts from "echarts";
import {EChartsType} from "echarts/core";
import {onMounted} from "vue";
import 'echarts-liquidfill/src/liquidFill.js'
import * as echarts from 'echarts'
import { EChartsType } from 'echarts/core'
import { onMounted } from 'vue'
let props = defineProps({
className: {
type: String,
default: 'chart'
},
config:{
type: Object,
default: ()=>{}
},
id: {
type: String,
default: 'chart'
},
width: {
type: String,
default: '200px'
},
height: {
type: String,
default: '200px'
}
})
const options = {
let props = defineProps({
className: {
type: String,
default: 'chart',
},
config: {
type: Object,
default: () => {},
},
id: {
type: String,
default: 'chart',
},
width: {
type: String,
default: '200px',
},
height: {
type: String,
default: '200px',
},
})
const options = {
legend: {
data: [
'3-11岁任务数',
@ -38,12 +38,12 @@ const options = {
'60岁全程接种量',
'80岁任务数',
'80岁全程接种量',
'完成率'
]
'完成率',
],
},
xAxis: {
type: 'category',
data: ['街道1', '街道2', '街道3', '街道4', '街道5', '街道6', '街道7']
data: ['街道1', '街道2', '街道3', '街道4', '街道5', '街道6', '街道7'],
},
yAxis: [
{ type: 'value' },
@ -54,7 +54,7 @@ const options = {
// max: 100,
nameTextStyle: {
color: '#ccc',
padding: [0, 0, 10, -30]
padding: [0, 0, 10, -30],
},
splitNumber: 5,
splitLine: {
@ -63,16 +63,16 @@ const options = {
type: 'dashed',
width: 1,
// 使
color: ['#566471', '#566471']
}
color: ['#566471', '#566471'],
},
},
axisLabel: {
show: true,
textStyle: {
fontSize: 12
}
}
}
fontSize: 12,
},
},
},
],
// tooltip: {
// trigger: 'axis',
@ -81,56 +81,60 @@ const options = {
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'shadow'
type: 'shadow',
},
textStyle: {
color: '#fff',
align: 'left',
fontSize: 14
fontSize: 14,
},
axisLine: {//x线
axisLine: {
//x线
show: true,
lineStyle: {//x线
color: '#000',//'#ccc' | 'rgb(128, 128, 128)' | 'rgba(128, 128, 128, 0.5)'
}
lineStyle: {
//x线
color: '#000', //'#ccc' | 'rgb(128, 128, 128)' | 'rgba(128, 128, 128, 0.5)'
},
},
backgroundColor: 'rgba(0,0,0,0.8)',
formatter: function (params) {
console.log(params);
let str = params[0].name + '<br />';
console.log(str);
console.log(params)
let str = params[0].name + '<br />'
console.log(str)
params.forEach((item) => {
console.log(item.seriesName);
console.log(item.seriesName)
if (item.value) {
if (item.seriesName.indexOf('岁全程接种量') != -1) {
str += `<span style="display:inline-block;margin-right:5px;border-radius:50%;width:10px;height:10px;left:5px;background-color: ${item.color}
str += `<span style="display:inline-block;margin-right:5px;border-radius:50%;width:10px;height:10px;left:5px;background-color: ${
item.color
}
"></span>
${item.seriesName}
:
${item.value} <br/>
&nbsp; &nbsp; 全程完成率
: ${item.value/100}%
<br/><br/>`;
}else if (item.seriesName.indexOf('岁任务数') != -1) {
: ${item.value / 100}%
<br/><br/>`
} else if (item.seriesName.indexOf('岁任务数') != -1) {
str += `<span style="display:inline-block;margin-right:5px;border-radius:50%;width:10px;height:10px;left:5px;background-color: ${item.color}
"></span>
${item.seriesName}
:
${item.value}
<br/>`;
}else{
<br/>`
} else {
str += `<span style="display:inline-block;margin-right:5px;border-radius:50%;width:10px;height:10px;left:5px;background-color: ${item.color}
"></span>
${item.seriesName}
:
${item.value}%
<br/>`;
<br/>`
}
}
});
return str;
}
})
return str
},
},
series: [
@ -138,77 +142,76 @@ const options = {
name: '3-11岁任务数',
data: [150, 230, 224, 218, 135, 147, 260],
stack: 'BB',
type: 'bar'
type: 'bar',
},
{
name: '3-11岁全程接种量',
data: [150, 230, 224, 218, 135, 147, 260],
stack: 'BB',
type: 'bar'
type: 'bar',
},
{
name: '60岁任务数',
data: [150, 230, 224, 218, 135, 147, 260],
stack: 'AA',
type: 'bar'
type: 'bar',
},
{
name: '60岁全程接种量',
data: [880, 30, 124, 118, 35, 47, 160],
stack: 'AA',
type: 'bar'
type: 'bar',
},
{
name: '80岁任务数',
data: [660, 30, 124, 118, 35, 47, 160],
stack: 'Ad',
type: 'bar'
type: 'bar',
},
{
name: '80岁全程接种量',
data: [880, 30, 124, 118, 35, 47, 160],
stack: 'Ad',
type: 'bar'
type: 'bar',
},
{
name: '完成率',
data: [50, 130, 124, 18, 35, 47, 160],
yAxisIndex:1,
yAxisIndex: 1,
type: 'line',
markLine: {
symbol: 'none',
itemStyle: {
normal: {
lineStyle: {
type: 'dotted'
}
}
type: 'dotted',
},
},
},
data: [{ type: 'average', name: 'Avg' + '%' }]
data: [{ type: 'average', name: 'Avg' + '%' }],
},
// symbol: 'none',
itemStyle: {
normal: {
lineStyle: {
width: 2,
type: 'solid' //'dotted'线 'solid'线
}
}
}
}
]
};
let chart:EChartsType;
const initChart =()=> {
let chart = echarts.init(document.getElementById(props.id))
chart.setOption(options)
return chart
}
onMounted(()=>{
chart = initChart()
window.addEventListener('resize',function (){
chart&&chart.resize()
type: 'solid', //'dotted'线 'solid'线
},
},
},
},
],
}
let chart: EChartsType
const initChart = () => {
let chart = echarts.init(document.getElementById(props.id))
chart.setOption(options)
return chart
}
onMounted(() => {
chart = initChart()
window.addEventListener('resize', function () {
chart && chart.resize()
})
})
})
</script>

View File

@ -1,79 +1,77 @@
<template>
<div :id="id" :class="className" :style="{height:height,width:width}" ref="chartsRef"/>
<div :id="id" :class="className" :style="{ height: height, width: width }" ref="chartsRef" />
</template>
<script lang="ts" setup>
import * as echarts from 'echarts'
import { EChartsType } from 'echarts/core'
import { onMounted, ref } from 'vue'
const chartsRef = ref<HTMLElement|null>()
import * as echarts from 'echarts'
import { EChartsType } from 'echarts/core'
import { onMounted, ref } from 'vue'
const chartsRef = ref<HTMLElement | null>()
const props = defineProps({
className: {
type: String,
default: 'chart'
},
xAxisData: {
type: Array,
default: () => ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
},
config: {
type: Object,
default: () => {}
},
seriesData: {
type: Array,
default: () => [150, 230, 224, 218, 135, 147, 260]
},
id: {
type: String,
default: 'chart'
},
width: {
type: String,
default: '200px'
},
height: {
type: String,
default: '200px'
}
})
const options = {
grid: {
top: 10,
left: '2%',
right: '2%',
bottom: '2%',
containLabel: true,
},
xAxis: {
type: 'category',
data: props.xAxisData
},
yAxis: {
type: 'value'
},
series: [
{
data: props.seriesData,
type: 'bar'
}
],
...props.config
}
let chart:EChartsType
const initChart = () => {
const chart = echarts.init(chartsRef.value)
chart.setOption(options)
return chart
}
onMounted(() => {
chart = initChart()
window.addEventListener('resize', function () {
chart && chart.resize()
const props = defineProps({
className: {
type: String,
default: 'chart',
},
xAxisData: {
type: Array,
default: () => ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
},
config: {
type: Object,
default: () => {},
},
seriesData: {
type: Array,
default: () => [150, 230, 224, 218, 135, 147, 260],
},
id: {
type: String,
default: 'chart',
},
width: {
type: String,
default: '200px',
},
height: {
type: String,
default: '200px',
},
})
const options = {
grid: {
top: 10,
left: '2%',
right: '2%',
bottom: '2%',
containLabel: true,
},
xAxis: {
type: 'category',
data: props.xAxisData,
},
yAxis: {
type: 'value',
},
series: [
{
data: props.seriesData,
type: 'bar',
},
],
...props.config,
}
let chart: EChartsType
const initChart = () => {
const chart = echarts.init(chartsRef.value)
chart.setOption(options)
return chart
}
onMounted(() => {
chart = initChart()
window.addEventListener('resize', function () {
chart && chart.resize()
})
})
})
</script>
<style>
</style>
<style></style>

View File

@ -1,102 +1,103 @@
<template>
<div class="item-charts">
<bar-charts width="100%" height="100%" :config="lineConfig"/>
<bar-charts width="100%" height="100%" :config="lineConfig" />
</div>
</template>
<script setup lang="ts">
import BarCharts from './components/bar.vue'
import { reactive } from 'vue'
const data = [154, 230, 224, 218, 135, 147, 260]
const color = ['#fa796f','#54c1fb','#ca6cd4','#59dcc1','#09a4ea','#e98f4d','#ea8e49']
const dataOptions = []
import BarCharts from './components/bar.vue'
import { reactive } from 'vue'
const data = [154, 230, 224, 218, 135, 147, 260]
const color = ['#fa796f', '#54c1fb', '#ca6cd4', '#59dcc1', '#09a4ea', '#e98f4d', '#ea8e49']
const dataOptions = []
data.forEach((item,index) => {
let obj = {
value: data[index],
itemStyle: {
color: color[index]
data.forEach((item, index) => {
let obj = {
value: data[index],
itemStyle: {
color: color[index],
},
}
}
dataOptions.push(obj)
})
dataOptions.push(obj)
})
const lineConfig = reactive({
color,
grid: {
top: '10%',
left: '3%',
right: '4%',
bottom: '10%',
containLabel: true
},
tooltip: {
trigger: 'axis',
backgroundColor: 'rgba(0,0,0,0.7)',
borderWidth: 0,
borderColor: 'rgba(0,0,0,0.7)',
formatter: (name, val) => {
const tipHtml = `
const lineConfig = reactive({
color,
grid: {
top: '10%',
left: '3%',
right: '4%',
bottom: '10%',
containLabel: true,
},
tooltip: {
trigger: 'axis',
backgroundColor: 'rgba(0,0,0,0.7)',
borderWidth: 0,
borderColor: 'rgba(0,0,0,0.7)',
formatter: (name, val) => {
const tipHtml = `
<div class="m-info" style=" opacity: 0.95;font-size: 12px; color: white;" >
<div class="title" ></div>
<div class="title" >完成占比${name[0].value}</div>
</div>`
return tipHtml
}
},
yAxis: {
//
axisLabel: {
color: '#bbdaff',
margin: 20 // 线
return tipHtml
},
},
axisTick: { // 线
show: false
yAxis: {
//
axisLabel: {
color: '#bbdaff',
margin: 20, // 线
},
axisTick: {
// 线
show: false,
},
// 线
splitLine: {
lineStyle: {
color: '#2d5baf',
},
},
},
// 线
splitLine: {
lineStyle: {
color: '#2d5baf'
}
}
},
xAxis: {
splitLine: {
show: false
},
// 线
axisLine: {
lineStyle: {
color: '#2d5baf'
}
},
type: 'category',
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
axisLabel: { //
color: '#bbdaff',
margin: 20 // 线
},
axisTick: { // 线
show: false
}
},
series: [
{
data: dataOptions,
type: 'bar',
barMaxWidth: 18,
markLine: {
silent: true
xAxis: {
splitLine: {
show: false,
},
// 线
axisLine: {
lineStyle: {
color: '#2d5baf',
},
},
type: 'category',
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
axisLabel: {
//
color: '#bbdaff',
margin: 20, // 线
},
}]
})
axisTick: {
// 线
show: false,
},
},
series: [
{
data: dataOptions,
type: 'bar',
barMaxWidth: 18,
markLine: {
silent: true,
},
},
],
})
</script>
<style lang="scss" scoped>
.item-charts{
height: 100%;
width: 100%;
}
.item-charts {
height: 100%;
width: 100%;
}
</style>

File diff suppressed because one or more lines are too long

View File

@ -1,79 +1,77 @@
<template>
<div :id="id" :class="className" :style="{height:height,width:width}" ref="chartsRef"/>
<div :id="id" :class="className" :style="{ height: height, width: width }" ref="chartsRef" />
</template>
<script lang="ts" setup>
import * as echarts from 'echarts'
import { EChartsType } from 'echarts/core'
import { onMounted, ref } from 'vue'
const chartsRef = ref<HTMLElement|null>()
import * as echarts from 'echarts'
import { EChartsType } from 'echarts/core'
import { onMounted, ref } from 'vue'
const chartsRef = ref<HTMLElement | null>()
const props = defineProps({
className: {
type: String,
default: 'chart'
},
xAxisData: {
type: Array,
default: () => ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
},
config: {
type: Object,
default: () => {}
},
seriesData: {
type: Array,
default: () => [150, 230, 224, 218, 135, 147, 260]
},
id: {
type: String,
default: 'chart'
},
width: {
type: String,
default: '200px'
},
height: {
type: String,
default: '200px'
}
})
const options = {
grid: {
top: 10,
left: '2%',
right: '2%',
bottom: '2%',
containLabel: true,
},
xAxis: {
type: 'category',
data: props.xAxisData
},
yAxis: {
type: 'value'
},
series: [
{
data: props.seriesData,
type: 'line'
}
],
...props.config
}
let chart:EChartsType
const initChart = () => {
const chart = echarts.init(chartsRef.value)
chart.setOption(options)
return chart
}
onMounted(() => {
chart = initChart()
window.addEventListener('resize', function () {
chart && chart.resize()
const props = defineProps({
className: {
type: String,
default: 'chart',
},
xAxisData: {
type: Array,
default: () => ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
},
config: {
type: Object,
default: () => {},
},
seriesData: {
type: Array,
default: () => [150, 230, 224, 218, 135, 147, 260],
},
id: {
type: String,
default: 'chart',
},
width: {
type: String,
default: '200px',
},
height: {
type: String,
default: '200px',
},
})
const options = {
grid: {
top: 10,
left: '2%',
right: '2%',
bottom: '2%',
containLabel: true,
},
xAxis: {
type: 'category',
data: props.xAxisData,
},
yAxis: {
type: 'value',
},
series: [
{
data: props.seriesData,
type: 'line',
},
],
...props.config,
}
let chart: EChartsType
const initChart = () => {
const chart = echarts.init(chartsRef.value)
chart.setOption(options)
return chart
}
onMounted(() => {
chart = initChart()
window.addEventListener('resize', function () {
chart && chart.resize()
})
})
})
</script>
<style>
</style>
<style></style>

View File

@ -1,79 +1,77 @@
<template>
<div :id="id" :class="className" :style="{height:height,width:width}" ref="chartsRef"/>
<div :id="id" :class="className" :style="{ height: height, width: width }" ref="chartsRef" />
</template>
<script lang="ts" setup>
import * as echarts from 'echarts'
import { EChartsType } from 'echarts/core'
import { onMounted, ref } from 'vue'
const chartsRef = ref<HTMLElement|null>()
import * as echarts from 'echarts'
import { EChartsType } from 'echarts/core'
import { onMounted, ref } from 'vue'
const chartsRef = ref<HTMLElement | null>()
const props = defineProps({
className: {
type: String,
default: 'chart'
},
xAxisData: {
type: Array,
default: () => ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
},
config: {
type: Object,
default: () => {}
},
seriesData: {
type: Array,
default: () => [150, 230, 224, 218, 135, 147, 260]
},
id: {
type: String,
default: 'chart'
},
width: {
type: String,
default: '200px'
},
height: {
type: String,
default: '200px'
}
})
const options = {
grid: {
top: 10,
left: '2%',
right: '2%',
bottom: '2%',
containLabel: true,
},
xAxis: {
type: 'category',
data: props.xAxisData
},
yAxis: {
type: 'value'
},
series: [
{
data: props.seriesData,
type: 'line'
}
],
...props.config
}
let chart:EChartsType
const initChart = () => {
const chart = echarts.init(chartsRef.value)
chart.setOption(options)
return chart
}
onMounted(() => {
chart = initChart()
window.addEventListener('resize', function () {
chart && chart.resize()
const props = defineProps({
className: {
type: String,
default: 'chart',
},
xAxisData: {
type: Array,
default: () => ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
},
config: {
type: Object,
default: () => {},
},
seriesData: {
type: Array,
default: () => [150, 230, 224, 218, 135, 147, 260],
},
id: {
type: String,
default: 'chart',
},
width: {
type: String,
default: '200px',
},
height: {
type: String,
default: '200px',
},
})
const options = {
grid: {
top: 10,
left: '2%',
right: '2%',
bottom: '2%',
containLabel: true,
},
xAxis: {
type: 'category',
data: props.xAxisData,
},
yAxis: {
type: 'value',
},
series: [
{
data: props.seriesData,
type: 'line',
},
],
...props.config,
}
let chart: EChartsType
const initChart = () => {
const chart = echarts.init(chartsRef.value)
chart.setOption(options)
return chart
}
onMounted(() => {
chart = initChart()
window.addEventListener('resize', function () {
chart && chart.resize()
})
})
})
</script>
<style>
</style>
<style></style>

View File

@ -1,96 +1,97 @@
<template>
<div class="item-charts">
<line-charts width="100%" height="100%" :config="lineConfig"/>
<line-charts width="100%" height="100%" :config="lineConfig" />
</div>
</template>
<script setup lang="ts">
import LineCharts from './components/line.vue'
import { reactive } from 'vue'
import LineCharts from './components/line.vue'
import { reactive } from 'vue'
const lineConfig = reactive({
grid: {
top: '10%',
left: '3%',
right: '4%',
bottom: '10%',
containLabel: true
},
tooltip: {
trigger: 'axis',
backgroundColor: 'rgba(0,0,0,0.7)',
borderWidth: 0,
borderColor: 'rgba(0,0,0,0.7)',
formatter: (name, val) => {
const tipHtml = `
const lineConfig = reactive({
grid: {
top: '10%',
left: '3%',
right: '4%',
bottom: '10%',
containLabel: true,
},
tooltip: {
trigger: 'axis',
backgroundColor: 'rgba(0,0,0,0.7)',
borderWidth: 0,
borderColor: 'rgba(0,0,0,0.7)',
formatter: (name, val) => {
const tipHtml = `
<div class="m-info" style=" opacity: 0.95;font-size: 12px; color: white;" >
<div class="title" ></div>
<div class="title" >完成占比${name[0].data}</div>
</div>`
return tipHtml
}
},
yAxis: {
//
axisLabel: {
color: '#bbdaff',
margin: 20 // 线
},
// 线
splitLine: {
lineStyle: {
color: '#2d5baf'
}
}
},
xAxis: {
splitLine: {
show: false
},
// 线
axisLine: {
lineStyle: {
color: '#2d5baf'
}
},
type: 'category',
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
axisLabel: { //
color: '#bbdaff',
margin: 20 // 线
},
boundaryGap: false, //
axisTick: { // 线
show: false
}
},
series: [
{
data: [154, 230, 224, 218, 135, 147, 260],
type: 'line',
// smooth:false, //true线线true
symbolSize: 12, //
symbol: 'circle',
markLine: {
silent: true
return tipHtml
},
itemStyle: {
normal: {
color: '#920783', // symbol
lineStyle: {
width: 3,
color: '#920783',
type: 'solid' // 'dotted'线 'solid'线
}
}
}
}]
})
},
yAxis: {
//
axisLabel: {
color: '#bbdaff',
margin: 20, // 线
},
// 线
splitLine: {
lineStyle: {
color: '#2d5baf',
},
},
},
xAxis: {
splitLine: {
show: false,
},
// 线
axisLine: {
lineStyle: {
color: '#2d5baf',
},
},
type: 'category',
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
axisLabel: {
//
color: '#bbdaff',
margin: 20, // 线
},
boundaryGap: false, //
axisTick: {
// 线
show: false,
},
},
series: [
{
data: [154, 230, 224, 218, 135, 147, 260],
type: 'line',
// smooth:false, //true线线true
symbolSize: 12, //
symbol: 'circle',
markLine: {
silent: true,
},
itemStyle: {
normal: {
color: '#920783', // symbol
lineStyle: {
width: 3,
color: '#920783',
type: 'solid', // 'dotted'线 'solid'线
},
},
},
},
],
})
</script>
<style lang="scss" scoped>
.item-charts{
height: 100%;
width: 100%;
}
.item-charts {
height: 100%;
width: 100%;
}
</style>

View File

@ -1,106 +1,105 @@
<template>
<div :id="id" :class="className" :style="{height:height,width:width}" />
<div :id="id" :class="className" :style="{ height: height, width: width }" />
</template>
<script lang="ts" setup>
import 'echarts-liquidfill/src/liquidFill.js'
import * as echarts from "echarts";
import {EChartsType} from "echarts/core";
import {onMounted} from "vue";
import 'echarts-liquidfill/src/liquidFill.js'
import * as echarts from 'echarts'
import { EChartsType } from 'echarts/core'
import { onMounted } from 'vue'
let props = defineProps({
className: {
type: String,
default: 'chart'
},
config:{
type: Object,
default: ()=>{}
},
id: {
type: String,
default: 'chart'
},
width: {
type: String,
default: '200px'
},
height: {
type: String,
default: '200px'
}
})
const options = {
grid: {
top: 10,
left: '2%',
right: '2%',
bottom: '2%',
containLabel: true
},
backgroundColor: '#0F224C', //
series: [
{
type: 'liquidFill', //
radius: '80%', //
center: ['50%', '50%'], //
amplitude: 20, //
data: [0.5,.5,.5], // data
color: [
{
type: 'linear',
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [
{
offset: 0,
color: '#446bf5',
},
{
offset: 1,
color: '#2ca3e2',
},
],
globalCoord: false,
},
], //
backgroundStyle: {
borderWidth: 1, //
// borderColor: '#23cc72', //
color: 'RGBA(51, 66, 127, 0.7)', //
},
label: {
//
position: ['50%', '45%'],
formatter: '50%', //,
textStyle: {
fontSize: '52px', //,
color: '#fff',
},
},
outline: {
// show: false
borderDistance: 0,
itemStyle: {
borderWidth: 2,
borderColor: '#112165',
},
},
let props = defineProps({
className: {
type: String,
default: 'chart',
},
config: {
type: Object,
default: () => {},
},
id: {
type: String,
default: 'chart',
},
width: {
type: String,
default: '200px',
},
height: {
type: String,
default: '200px',
},
],
};
let chart:EChartsType;
const initChart =()=> {
let chart = echarts.init(document.getElementById(props.id))
chart.setOption(options)
return chart
}
onMounted(()=>{
chart = initChart()
window.addEventListener('resize',function (){
chart&&chart.resize()
})
})
const options = {
grid: {
top: 10,
left: '2%',
right: '2%',
bottom: '2%',
containLabel: true,
},
backgroundColor: '#0F224C', //
series: [
{
type: 'liquidFill', //
radius: '80%', //
center: ['50%', '50%'], //
amplitude: 20, //
data: [0.5, 0.5, 0.5], // data
color: [
{
type: 'linear',
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [
{
offset: 0,
color: '#446bf5',
},
{
offset: 1,
color: '#2ca3e2',
},
],
globalCoord: false,
},
], //
backgroundStyle: {
borderWidth: 1, //
// borderColor: '#23cc72', //
color: 'RGBA(51, 66, 127, 0.7)', //
},
label: {
//
position: ['50%', '45%'],
formatter: '50%', //,
textStyle: {
fontSize: '52px', //,
color: '#fff',
},
},
outline: {
// show: false
borderDistance: 0,
itemStyle: {
borderWidth: 2,
borderColor: '#112165',
},
},
},
],
}
let chart: EChartsType
const initChart = () => {
let chart = echarts.init(document.getElementById(props.id))
chart.setOption(options)
return chart
}
onMounted(() => {
chart = initChart()
window.addEventListener('resize', function () {
chart && chart.resize()
})
})
</script>

View File

@ -1,271 +1,269 @@
<template>
<div :id="id" :class="className" :style="{height:height,width:width}" />
<div :id="id" :class="className" :style="{ height: height, width: width }" />
</template>
<script lang="ts" setup>
import * as echarts from "echarts";
import {EChartsType} from "echarts/core";
import {onMounted} from "vue";
import * as echarts from 'echarts'
import { EChartsType } from 'echarts/core'
import { onMounted } from 'vue'
let props = defineProps({
className: {
type: String,
default: 'chart'
},
config:{
type: Object,
default: ()=>{}
},
id: {
type: String,
default: 'chart'
},
width: {
type: String,
default: '200px'
},
height: {
type: String,
default: '200px'
}
})
const color = ['#3c90ff', '#fff225', '#24ffdf', '#ff9c3c', '#7536ff']
const indicator = [
{
text: '文明村',
min: 0,
max: 100
},
{
text: '卫生村',
min: 0,
max: 100
},
{
text: '森林村庄',
min: 0,
max: 100
},
{
text: '全面小康',
min: 0,
max: 100
},
{
text: '景区村庄',
min: 0,
max: 100
}
]
const Data = [80,61,70,86,77]
function setData() {
return [
let props = defineProps({
className: {
type: String,
default: 'chart',
},
config: {
type: Object,
default: () => {},
},
id: {
type: String,
default: 'chart',
},
width: {
type: String,
default: '200px',
},
height: {
type: String,
default: '200px',
},
})
const color = ['#3c90ff', '#fff225', '#24ffdf', '#ff9c3c', '#7536ff']
const indicator = [
{
value: Data,
itemStyle: {
normal: {
lineStyle: {
color: '#4BFFFC',
shadowColor: '#4BFFFC',
shadowBlur: 5
},
shadowColor: '#4BFFFC',
shadowBlur: 5
}
},
areaStyle: {
normal: {
//
color: {
type: 'radial',
x: 0.5, //
y: 0.5, //
r: 1,
colorStops: [
{
offset: 1,
color: '#4BFFFC'
},
{
offset: 0,
color: 'rgba(0,0,0,0)'
}
],
globalCoord: false
},
opacity: 0.8 //
}
}
}
text: '文明村',
min: 0,
max: 100,
},
{
text: '卫生村',
min: 0,
max: 100,
},
{
text: '森林村庄',
min: 0,
max: 100,
},
{
text: '全面小康',
min: 0,
max: 100,
},
{
text: '景区村庄',
min: 0,
max: 100,
},
]
}
function setgauge(i) {
return {
type: 'gauge',
detail: false,
splitNumber: 10, //
radius: '80%', //
center: ['50%', '50%'],
startAngle: 90 + 72 * i + 18, //
endAngle: 90 + 72 * (i + 1) - 18, //
axisLine: {
show: false
},
axisTick: {
show: true,
lineStyle: {
color: '#66ccff',
width: 1
const Data = [80, 61, 70, 86, 77]
function setData() {
return [
{
value: Data,
itemStyle: {
normal: {
lineStyle: {
color: '#4BFFFC',
shadowColor: '#4BFFFC',
shadowBlur: 5,
},
shadowColor: '#4BFFFC',
shadowBlur: 5,
},
},
areaStyle: {
normal: {
//
color: {
type: 'radial',
x: 0.5, //
y: 0.5, //
r: 1,
colorStops: [
{
offset: 1,
color: '#4BFFFC',
},
{
offset: 0,
color: 'rgba(0,0,0,0)',
},
],
globalCoord: false,
},
opacity: 0.8, //
},
},
},
]
}
function setgauge(i) {
return {
type: 'gauge',
detail: false,
splitNumber: 10, //
radius: '80%', //
center: ['50%', '50%'],
startAngle: 90 + 72 * i + 18, //
endAngle: 90 + 72 * (i + 1) - 18, //
axisLine: {
show: false,
},
axisTick: {
show: true,
lineStyle: {
color: '#66ccff',
width: 1,
},
length: 6,
splitNumber: 1,
},
splitLine: {
show: false,
},
axisLabel: {
show: false,
},
length: 6,
splitNumber: 1
},
splitLine: {
show: false
},
axisLabel: {
show: false
}
}
}
function setSpot() {
var scatterData = []
Data.map((o, i) => {
scatterData.push({
value: [o, i],
itemStyle: {
normal: {
color: color[i],
borderColor: '#fff',
borderWidth: 1,
shadowColor: color[i],
shadowBlur: 8
}
}
function setSpot() {
var scatterData = []
Data.map((o, i) => {
scatterData.push({
value: [o, i],
itemStyle: {
normal: {
color: color[i],
borderColor: '#fff',
borderWidth: 1,
shadowColor: color[i],
shadowBlur: 8,
},
},
})
})
return scatterData
}
const options = {
backgroundColor: '#0E1327',
polar: {
center: ['50%', '50%'],
radius: '60%',
},
radar: {
shape: 'circle',
center: ['50%', '50%'],
radius: '60%',
indicator: indicator,
axisName: {
color: '#b7e9fd',
fontSize: 13,
padding: -20,
},
nameGap: 45,
splitNumber: 4,
splitArea: {
// grid
show: true,
areaStyle: {
//
color: ['rgba(27, 50, 66, 0.4)'],
},
},
axisLine: {
//线
lineStyle: {
color: '#5aa3d0',
},
},
splitLine: {
lineStyle: {
color: 'rgba(99,192,251,0.2)', // 线
width: 2, // 线线
},
},
},
angleAxis: {
type: 'category',
data: name,
minInterval: 1,
boundaryGap: false,
clockwise: false,
axisTick: {
show: false,
},
axisLabel: {
show: false,
},
axisLine: {
show: false,
},
splitLine: {
show: false,
},
},
radiusAxis: {
min: 0,
max: 100,
interval: 25,
splitLine: {
show: false,
},
axisTick: {
show: false,
},
axisLine: {
//线
lineStyle: {
color: '#5aa3d0',
},
},
axisLabel: {
fontSize: 12,
color: '#5aa3d0',
align: 'left',
margin: -5,
},
},
series: [
setgauge(0),
setgauge(1),
setgauge(2),
setgauge(3),
setgauge(4),
{
type: 'radar',
silent: true,
lineStyle: {
color: '#66ffff',
},
areaStyle: {
color: 'rgba(102, 255, 255, 0.31)',
},
data: setData(),
},
{
type: 'scatter',
coordinateSystem: 'polar',
symbolSize: 20,
data: setSpot(),
},
],
}
let chart: EChartsType
const initChart = () => {
let chart = echarts.init(document.getElementById(props.id))
chart.setOption(options)
return chart
}
onMounted(() => {
chart = initChart()
window.addEventListener('resize', function () {
chart && chart.resize()
})
})
return scatterData
}
const options = {
backgroundColor: '#0E1327',
polar: {
center: ['50%', '50%'],
radius: '60%'
},
radar: {
shape: 'circle',
center: ['50%', '50%'],
radius: '60%',
indicator: indicator,
axisName: {
color: '#b7e9fd',
fontSize: 13,
padding: -20
},
nameGap: 45,
splitNumber: 4,
splitArea: {
// grid
show: true,
areaStyle: {
//
color: ['rgba(27, 50, 66, 0.4)']
}
},
axisLine: {
//线
lineStyle: {
color: '#5aa3d0'
}
},
splitLine: {
lineStyle: {
color: 'rgba(99,192,251,0.2)', // 线
width: 2 // 线线
}
}
},
angleAxis: {
type: 'category',
data: name,
minInterval: 1,
boundaryGap: false,
clockwise: false,
axisTick: {
show: false
},
axisLabel: {
show: false
},
axisLine: {
show: false
},
splitLine: {
show: false
}
},
radiusAxis: {
min: 0,
max: 100,
interval: 25,
splitLine: {
show: false
},
axisTick: {
show: false
},
axisLine: {
//线
lineStyle: {
color: '#5aa3d0'
}
},
axisLabel: {
fontSize: 12,
color: '#5aa3d0',
align: 'left',
margin: -5
}
},
series: [
setgauge(0),
setgauge(1),
setgauge(2),
setgauge(3),
setgauge(4),
{
type: 'radar',
silent: true,
lineStyle: {
color: '#66ffff'
},
areaStyle: {
color: 'rgba(102, 255, 255, 0.31)'
},
data: setData()
},
{
type: 'scatter',
coordinateSystem: 'polar',
symbolSize: 20,
data: setSpot()
}
]
};
let chart:EChartsType;
const initChart =()=> {
let chart = echarts.init(document.getElementById(props.id))
chart.setOption(options)
return chart
}
onMounted(()=>{
chart = initChart()
window.addEventListener('resize',function (){
chart&&chart.resize()
})
})
</script>

View File

@ -1,200 +1,201 @@
<template>
<div :id="id" :class="className" :style="{height:height,width:width}" />
<div :id="id" :class="className" :style="{ height: height, width: width }" />
</template>
<script lang="ts" setup>
import * as echarts from "echarts";
import {EChartsType} from "echarts/core";
import {onMounted} from "vue";
import * as echarts from 'echarts'
import { EChartsType } from 'echarts/core'
import { onMounted } from 'vue'
let props = defineProps({
className: {
type: String,
default: 'chart'
},
config:{
type: Object,
default: ()=>{}
},
id: {
type: String,
default: 'chart'
},
width: {
type: String,
default: '200px'
},
height: {
type: String,
default: '200px'
}
})
let color = ['#0E7CE2', '#FF8352', '#E271DE', '#F8456B', '#00FFFF', '#4AEAB0'];
let echartData = [
{
name: '设备1',
value: '3720',
},
{
name: '设备2',
value: '2920',
},
{
name: '设备3',
value: '2200',
},
{
name: '设备4',
value: '1420',
},
];
let formatNumber = function (num) {
let reg = /(?=(\B)(\d{3})+$)/g;
return num.toString().replace(reg, ',');
};
const options = {
backgroundColor: '#364686',
color: color,
title: [
{
text: '设备数',
x: 'center',
top: '40%',
textStyle: {
color: '#fff',
fontSize: 18,
fontWeight: '100',
},
let props = defineProps({
className: {
type: String,
default: 'chart',
},
{
text: '60%',
x: 'center',
top: '50%',
textStyle: {
fontSize: 30,
color: '#00f0ff',
foontWeight: '500',
},
config: {
type: Object,
default: () => {},
},
],
polar: {
radius: ['44%', '50%'],
center: ['50%', '50%'],
},
angleAxis: {
max: 100,
show: false,
},
radiusAxis: {
type: 'category',
show: true,
axisLabel: {
show: false,
id: {
type: String,
default: 'chart',
},
axisLine: {
show: false,
width: {
type: String,
default: '200px',
},
axisTick: {
show: false,
height: {
type: String,
default: '200px',
},
},
series: [
{
type: 'pie',
radius: ['55%', '67%'],
center: ['50%', '50%'],
data: echartData,
hoverAnimation: false,
itemStyle: {
normal: {
borderColor: '#364684',
borderWidth: 2,
},
},
labelLine: {
normal: {
length: 60,
length2: 60,
lineStyle: {
color: '#e6e6e6',
},
},
},
label: {
normal: {
formatter: (params) => {
return '{icon|●}{name|' + params.name + '}\n{value|' + formatNumber(params.value) + '}';
},
padding: [0, -70, 30, -70],
rich: {
icon: {
fontSize: 14,
align: 'left',
padding: [4, 0, 0, 0],
},
name: {
fontSize: 14,
align: 'left',
padding: [4, 0, 0, 0],
color: '#fff',
},
value: {
fontSize: 18,
fontWeight: 'bold',
color: '#fff',
align: 'left',
},
},
},
},
},
{
name: '',
type: 'pie',
startAngle: 90,
radius: '50%',
hoverAnimation: false,
center: ['50%', '50%'],
itemStyle: {
normal: {
labelLine: {
show: false,
},
color: new echarts.graphic.RadialGradient(0.5, 0.5, 1, [
{
offset: 1,
color: 'rgba(50,171,241, 1)',
},
{
offset: 0,
color: 'rgba(55,70,130, 0)',
},
]),
// borderWidth: 1,
// borderColor: '',
shadowBlur: 10,
// shadowColor: 'rgba(55,70,130, 1)'
},
},
data: [
{
value: 100,
},
],
},
],
};
let chart:EChartsType;
const initChart =()=> {
let chart = echarts.init(document.getElementById(props.id))
chart.setOption(options)
return chart
}
onMounted(()=>{
chart = initChart()
window.addEventListener('resize',function (){
chart&&chart.resize()
})
let color = ['#0E7CE2', '#FF8352', '#E271DE', '#F8456B', '#00FFFF', '#4AEAB0']
let echartData = [
{
name: '设备1',
value: '3720',
},
{
name: '设备2',
value: '2920',
},
{
name: '设备3',
value: '2200',
},
{
name: '设备4',
value: '1420',
},
]
let formatNumber = function (num) {
let reg = /(?=(\B)(\d{3})+$)/g
return num.toString().replace(reg, ',')
}
})
const options = {
backgroundColor: '#364686',
color: color,
title: [
{
text: '设备数',
x: 'center',
top: '40%',
textStyle: {
color: '#fff',
fontSize: 18,
fontWeight: '100',
},
},
{
text: '60%',
x: 'center',
top: '50%',
textStyle: {
fontSize: 30,
color: '#00f0ff',
foontWeight: '500',
},
},
],
polar: {
radius: ['44%', '50%'],
center: ['50%', '50%'],
},
angleAxis: {
max: 100,
show: false,
},
radiusAxis: {
type: 'category',
show: true,
axisLabel: {
show: false,
},
axisLine: {
show: false,
},
axisTick: {
show: false,
},
},
series: [
{
type: 'pie',
radius: ['55%', '67%'],
center: ['50%', '50%'],
data: echartData,
hoverAnimation: false,
itemStyle: {
normal: {
borderColor: '#364684',
borderWidth: 2,
},
},
labelLine: {
normal: {
length: 60,
length2: 60,
lineStyle: {
color: '#e6e6e6',
},
},
},
label: {
normal: {
formatter: (params) => {
return (
'{icon|●}{name|' + params.name + '}\n{value|' + formatNumber(params.value) + '}'
)
},
padding: [0, -70, 30, -70],
rich: {
icon: {
fontSize: 14,
align: 'left',
padding: [4, 0, 0, 0],
},
name: {
fontSize: 14,
align: 'left',
padding: [4, 0, 0, 0],
color: '#fff',
},
value: {
fontSize: 18,
fontWeight: 'bold',
color: '#fff',
align: 'left',
},
},
},
},
},
{
name: '',
type: 'pie',
startAngle: 90,
radius: '50%',
hoverAnimation: false,
center: ['50%', '50%'],
itemStyle: {
normal: {
labelLine: {
show: false,
},
color: new echarts.graphic.RadialGradient(0.5, 0.5, 1, [
{
offset: 1,
color: 'rgba(50,171,241, 1)',
},
{
offset: 0,
color: 'rgba(55,70,130, 0)',
},
]),
// borderWidth: 1,
// borderColor: '',
shadowBlur: 10,
// shadowColor: 'rgba(55,70,130, 1)'
},
},
data: [
{
value: 100,
},
],
},
],
}
let chart: EChartsType
const initChart = () => {
let chart = echarts.init(document.getElementById(props.id))
chart.setOption(options)
return chart
}
onMounted(() => {
chart = initChart()
window.addEventListener('resize', function () {
chart && chart.resize()
})
})
</script>

View File

@ -1,149 +1,147 @@
<template>
<div :id="id" :class="className" :style="{height:height,width:width}" />
<div :id="id" :class="className" :style="{ height: height, width: width }" />
</template>
<script lang="ts" setup>
import * as echarts from "echarts";
import {EChartsType} from "echarts/core";
import {onMounted} from "vue";
import * as echarts from 'echarts'
import { EChartsType } from 'echarts/core'
import { onMounted } from 'vue'
let props = defineProps({
className: {
type: String,
default: 'chart'
},
config:{
type: Object,
default: ()=>{}
},
id: {
type: String,
default: 'chart'
},
width: {
type: String,
default: '200px'
},
height: {
type: String,
default: '200px'
}
})
const options = {
title: [
{
text: '已完成',
x: 'center',
top: '52%',
textStyle: {
color: '#FFFFFF',
fontSize: 16,
fontWeight: '100',
},
let props = defineProps({
className: {
type: String,
default: 'chart',
},
{
text: '75%',
x: 'center',
y: 'center',
textStyle: {
fontSize: '12',
color: '#FFFFFF',
fontFamily: 'DINAlternate-Bold, DINAlternate',
foontWeight: '600',
},
config: {
type: Object,
default: () => {},
},
],
backgroundColor: '#111',
polar: {
radius: ['42%', '52%'],
center: ['50%', '50%'],
},
angleAxis: {
max: 100,
show: false,
},
radiusAxis: {
type: 'category',
show: true,
axisLabel: {
show: false,
id: {
type: String,
default: 'chart',
},
axisLine: {
show: false,
width: {
type: String,
default: '200px',
},
axisTick: {
show: false,
height: {
type: String,
default: '200px',
},
},
series: [
{
name: '',
type: 'bar',
roundCap: true,
barWidth: 30,
showBackground: true,
backgroundStyle: {
color: 'rgba(66, 66, 66, .3)',
},
data: [60],
coordinateSystem: 'polar',
itemStyle: {
normal: {
color: new echarts.graphic.LinearGradient(0, 1, 0, 0, [
{
offset: 0,
color: '#16CEB9',
},
{
offset: 1,
color: '#6648FF',
},
]),
},
},
},
{
name: '',
type: 'pie',
startAngle: 80,
radius: ['56%'],
hoverAnimation: false,
center: ['50%', '50%'],
itemStyle: {
color: 'rgba(66, 66, 66, .1)',
borderWidth: 1,
borderColor: '#5269EE',
},
data: [100],
},
{
name: '',
type: 'pie',
startAngle: 80,
radius: ['38%'],
hoverAnimation: false,
center: ['50%', '50%'],
itemStyle: {
color: 'rgba(66, 66, 66, .1)',
borderWidth: 1,
borderColor: '#5269EE',
},
data: [100],
},
],
};
let chart:EChartsType;
const initChart =()=> {
let chart = echarts.init(document.getElementById(props.id))
chart.setOption(options)
return chart
}
onMounted(()=>{
chart = initChart()
window.addEventListener('resize',function (){
chart&&chart.resize()
})
})
const options = {
title: [
{
text: '已完成',
x: 'center',
top: '52%',
textStyle: {
color: '#FFFFFF',
fontSize: 16,
fontWeight: '100',
},
},
{
text: '75%',
x: 'center',
y: 'center',
textStyle: {
fontSize: '12',
color: '#FFFFFF',
fontFamily: 'DINAlternate-Bold, DINAlternate',
foontWeight: '600',
},
},
],
backgroundColor: '#111',
polar: {
radius: ['42%', '52%'],
center: ['50%', '50%'],
},
angleAxis: {
max: 100,
show: false,
},
radiusAxis: {
type: 'category',
show: true,
axisLabel: {
show: false,
},
axisLine: {
show: false,
},
axisTick: {
show: false,
},
},
series: [
{
name: '',
type: 'bar',
roundCap: true,
barWidth: 30,
showBackground: true,
backgroundStyle: {
color: 'rgba(66, 66, 66, .3)',
},
data: [60],
coordinateSystem: 'polar',
itemStyle: {
normal: {
color: new echarts.graphic.LinearGradient(0, 1, 0, 0, [
{
offset: 0,
color: '#16CEB9',
},
{
offset: 1,
color: '#6648FF',
},
]),
},
},
},
{
name: '',
type: 'pie',
startAngle: 80,
radius: ['56%'],
hoverAnimation: false,
center: ['50%', '50%'],
itemStyle: {
color: 'rgba(66, 66, 66, .1)',
borderWidth: 1,
borderColor: '#5269EE',
},
data: [100],
},
{
name: '',
type: 'pie',
startAngle: 80,
radius: ['38%'],
hoverAnimation: false,
center: ['50%', '50%'],
itemStyle: {
color: 'rgba(66, 66, 66, .1)',
borderWidth: 1,
borderColor: '#5269EE',
},
data: [100],
},
],
}
let chart: EChartsType
const initChart = () => {
let chart = echarts.init(document.getElementById(props.id))
chart.setOption(options)
return chart
}
onMounted(() => {
chart = initChart()
window.addEventListener('resize', function () {
chart && chart.resize()
})
})
</script>

View File

@ -1,85 +1,104 @@
<template>
<div :id="id" :class="className" :style="{height:height,width:width}" />
<div :id="id" :class="className" :style="{ height: height, width: width }" />
</template>
<script lang="ts" setup>
import * as echarts from "echarts";
import {EChartsType} from "echarts/core";
import {onMounted} from "vue";
import * as echarts from 'echarts'
import { EChartsType } from 'echarts/core'
import { onMounted } from 'vue'
let props = defineProps({
className: {
type: String,
default: 'chart'
},
config:{
type: Object,
default: ()=>{}
},
id: {
type: String,
default: 'chart'
},
width: {
type: String,
default: '200px'
},
height: {
type: String,
default: '200px'
}
})
var data = [],data2=[];
var trafficWay = [
{
name: '病假',
value: 20
},{
name: '事假',
value: 1
},{
name: '婚假',
value: 30
},{
name: '丧假',
value: 40
},{
name: '年休假',
value: 40
}];
var color=['#2A8BFD','#BAFF7F','#00FAC1','#00CAFF','#FDE056','#4ED33C','#FF8A26','#FF5252','#9689FF','#CB00FF']
for (var i = 0; i < trafficWay.length; i++) {
data.push({
value: trafficWay[i].value,
name: trafficWay[i].name,
itemStyle: {
normal: {
borderWidth: 8,
shadowBlur: 20,
borderRadius:20,
borderColor:color[i],
shadowColor: color[i]
}
}
}, {
value: 5,
name: '',
itemStyle: {
normal: {
label: {
show: false
let props = defineProps({
className: {
type: String,
default: 'chart',
},
config: {
type: Object,
default: () => {},
},
id: {
type: String,
default: 'chart',
},
width: {
type: String,
default: '200px',
},
height: {
type: String,
default: '200px',
},
})
var data = [],
data2 = []
var trafficWay = [
{
name: '病假',
value: 20,
},
{
name: '事假',
value: 1,
},
{
name: '婚假',
value: 30,
},
{
name: '丧假',
value: 40,
},
{
name: '年休假',
value: 40,
},
]
var color = [
'#2A8BFD',
'#BAFF7F',
'#00FAC1',
'#00CAFF',
'#FDE056',
'#4ED33C',
'#FF8A26',
'#FF5252',
'#9689FF',
'#CB00FF',
]
for (var i = 0; i < trafficWay.length; i++) {
data.push(
{
value: trafficWay[i].value,
name: trafficWay[i].name,
itemStyle: {
normal: {
borderWidth: 8,
shadowBlur: 20,
borderRadius: 20,
borderColor: color[i],
shadowColor: color[i],
},
},
labelLine: {
show: false
},
{
value: 5,
name: '',
itemStyle: {
normal: {
label: {
show: false,
},
labelLine: {
show: false,
},
color: 'rgba(0, 0, 0, 0)',
borderColor: 'rgba(0, 0, 0, 0)',
borderWidth: 0,
},
},
color: 'rgba(0, 0, 0, 0)',
borderColor: 'rgba(0, 0, 0, 0)',
borderWidth: 0
}
}
});
data2.push({
},
)
data2.push(
{
value: trafficWay[i].value,
name: trafficWay[i].name,
},
@ -89,325 +108,330 @@ for (var i = 0; i < trafficWay.length; i++) {
itemStyle: {
normal: {
label: {
show: false
show: false,
},
labelLine: {
show: false
show: false,
},
color: 'rgba(0, 0, 0, 0)',
borderColor: 'rgba(0, 0, 0, 0)',
borderWidth: 0,
opacity:0.2
}
}
}
)
}
let angle = 0;//
const option = {
backgroundColor:"#061740",
color : color,
legend:{
right:'10%',
top:'10%',
icon:'rect',
itemWidth:15,
itemHeight:15,
textStyle:{
color:'#ffffff',
}
},
series: [
{//线1
name: "ring5",
type: 'custom',
coordinateSystem: "none",
renderItem: function(params, api) {
return {
type: 'arc',
shape: {
cx: api.getWidth() / 3,
cy: api.getHeight() / 2,
r: Math.min(api.getWidth(), api.getHeight()) / 2 * 0.6,
startAngle: (0+angle) * Math.PI / 180,
endAngle: (90+angle) * Math.PI / 180
opacity: 0.2,
},
style: {
stroke: '#4EE9E6',
fill: "transparent",
lineWidth: 1.5
},
silent: true
};
},
},
data: [0]
},
{//线1
name: "ring5",
type: 'custom',
coordinateSystem: "none",
renderItem: function(params, api) {
return {
type: 'arc',
shape: {
cx: api.getWidth() / 3,
cy: api.getHeight() / 2,
r: Math.min(api.getWidth(), api.getHeight()) / 2 * 0.6,
startAngle: (180+angle) * Math.PI / 180,
endAngle: (270+angle) * Math.PI / 180
},
style: {
stroke: "#4EE9E6",
fill: "transparent",
lineWidth: 1.5
},
silent: true
};
},
data: [0]
},
{//线2
name: "ring5",
type: 'custom',
coordinateSystem: "none",
renderItem: function(params, api) {
return {
type: 'arc',
shape: {
cx: api.getWidth() / 3,
cy: api.getHeight() / 2,
r: Math.min(api.getWidth(), api.getHeight()) / 2 * 0.65,
startAngle: (270+-angle) * Math.PI / 180,
endAngle: (40+-angle) * Math.PI / 180
},
style: {
stroke: "#4EE9E6",
fill: "transparent",
lineWidth: 1.5
},
silent: true
};
},
data: [0]
},
{//线2
name: "ring5",
type: 'custom',
coordinateSystem: "none",
renderItem: function(params, api) {
return {
type: 'arc',
shape: {
cx: api.getWidth() / 3,
cy: api.getHeight() / 2,
r: Math.min(api.getWidth(), api.getHeight()) / 2 * 0.65,
startAngle: (90+-angle) * Math.PI / 180,
endAngle: (220+-angle) * Math.PI / 180
},
style: {
stroke: "#4EE9E6",
fill: "transparent",
lineWidth: 1.5
},
silent: true
};
},
data: [0]
},
{//绿1
name: "ring5",
type: 'custom',
coordinateSystem: "none",
renderItem: function(params, api) {
let x0 = api.getWidth() / 3;
let y0 = api.getHeight() / 2;
let r = Math.min(api.getWidth(), api.getHeight()) / 2 * 0.65;
let point = getCirlPoint(x0, y0, r, (90+-angle))
return {
type: 'circle',
shape: {
cx: point.x,
cy: point.y,
r: 4
},
style: {
stroke: "#66FFFF",//
fill: "#66FFFF"
},
silent: true
};
},
data: [0]
},
{//绿2
name: "ring5", //绿
type: 'custom',
coordinateSystem: "none",
renderItem: function(params, api) {
let x0 = api.getWidth() / 3;
let y0 = api.getHeight() / 2;
let r = Math.min(api.getWidth(), api.getHeight()) / 2 * 0.65;
let point = getCirlPoint(x0, y0, r, (270+-angle))
return {
type: 'circle',
shape: {
cx: point.x,
cy: point.y,
r: 4
},
style: {
stroke: "#66FFFF",//
fill: "#66FFFF"
},
silent: true
};
},
data: [0]
},
{//绿3
name: "ring5",
type: 'custom',
coordinateSystem: "none",
renderItem: function(params, api) {
let x0 = api.getWidth() / 3;
let y0 = api.getHeight() / 2;
let r = Math.min(api.getWidth(), api.getHeight()) / 2 * 0.6;
let point = getCirlPoint(x0, y0, r, (90+angle))
return {
type: 'circle',
shape: {
cx: point.x,
cy: point.y,
r: 4
},
style: {
stroke: "#66FFFF",//
fill: "#66FFFF"
},
silent: true
};
},
data: [0]
},
{//绿4
name: "ring5", //绿
type: 'custom',
coordinateSystem: "none",
renderItem: function(params, api) {
let x0 = api.getWidth() / 3;
let y0 = api.getHeight() / 2;
let r = Math.min(api.getWidth(), api.getHeight()) / 2 * 0.6;
let point = getCirlPoint(x0, y0, r, (270+angle))
return {
type: 'circle',
shape: {
cx: point.x,
cy: point.y,
r: 4
},
style: {
stroke: "#66FFFF",//
fill: "#66FFFF"
},
silent: true
};
},
data: [0]
},
{
name: '',
type: 'pie',
clockWise: false,
radius: ['98%', '95%'],
hoverAnimation: false,
center:['33.33%','50%'],
top:"center",
itemStyle: {
normal:{
label: {
show:false
}
}
},
data:data
},
{
type: 'pie',
top:"center",
startAngle:90,
clockwise:false,
center:['33.33%','50%'],
legendHoverLink:false,
hoverAnimation: false,
radius: ['94%', '55%'],
itemStyle: {
opacity:0.15
},
label: {
show: false,
position: 'center'
},
labelLine: {
show: false
},
data:data2
},
{
name: '',
type: 'pie',
clockWise: false,
center:['33.33%','50%'],
radius: ['39%', '38%'],
hoverAnimation: false,
top:"center",
itemStyle: {
normal:{
label: {
show:false
}
}
},
data:data
},
]
};
//(x0,y0rangle)
function getCirlPoint(x0, y0, r, angle) {
let x1 = x0 + r * Math.cos(angle * Math.PI / 180)
let y1 = y0 + r * Math.sin(angle * Math.PI / 180)
return {
x: x1,
y: y1
)
}
}
let angle = 0 //
let chart:EChartsType;
const initChart =()=> {
let chart = echarts.init(document.getElementById(props.id))
draw(chart)
return chart
}
function draw(chart){
angle = angle+3
chart.setOption(option, true)
//window.requestAnimationFrame(draw);
}
const option = {
backgroundColor: '#061740',
color: color,
legend: {
right: '10%',
top: '10%',
icon: 'rect',
itemWidth: 15,
itemHeight: 15,
textStyle: {
color: '#ffffff',
},
},
series: [
{
//线1
name: 'ring5',
type: 'custom',
coordinateSystem: 'none',
renderItem: function (params, api) {
return {
type: 'arc',
shape: {
cx: api.getWidth() / 3,
cy: api.getHeight() / 2,
r: (Math.min(api.getWidth(), api.getHeight()) / 2) * 0.6,
startAngle: ((0 + angle) * Math.PI) / 180,
endAngle: ((90 + angle) * Math.PI) / 180,
},
style: {
stroke: '#4EE9E6',
fill: 'transparent',
lineWidth: 1.5,
},
silent: true,
}
},
data: [0],
},
{
//线1
name: 'ring5',
type: 'custom',
coordinateSystem: 'none',
renderItem: function (params, api) {
return {
type: 'arc',
shape: {
cx: api.getWidth() / 3,
cy: api.getHeight() / 2,
r: (Math.min(api.getWidth(), api.getHeight()) / 2) * 0.6,
startAngle: ((180 + angle) * Math.PI) / 180,
endAngle: ((270 + angle) * Math.PI) / 180,
},
style: {
stroke: '#4EE9E6',
fill: 'transparent',
lineWidth: 1.5,
},
silent: true,
}
},
data: [0],
},
{
//线2
name: 'ring5',
type: 'custom',
coordinateSystem: 'none',
renderItem: function (params, api) {
return {
type: 'arc',
shape: {
cx: api.getWidth() / 3,
cy: api.getHeight() / 2,
r: (Math.min(api.getWidth(), api.getHeight()) / 2) * 0.65,
startAngle: ((270 + -angle) * Math.PI) / 180,
endAngle: ((40 + -angle) * Math.PI) / 180,
},
style: {
stroke: '#4EE9E6',
fill: 'transparent',
lineWidth: 1.5,
},
silent: true,
}
},
data: [0],
},
{
//线2
name: 'ring5',
type: 'custom',
coordinateSystem: 'none',
renderItem: function (params, api) {
return {
type: 'arc',
shape: {
cx: api.getWidth() / 3,
cy: api.getHeight() / 2,
r: (Math.min(api.getWidth(), api.getHeight()) / 2) * 0.65,
startAngle: ((90 + -angle) * Math.PI) / 180,
endAngle: ((220 + -angle) * Math.PI) / 180,
},
style: {
stroke: '#4EE9E6',
fill: 'transparent',
lineWidth: 1.5,
},
silent: true,
}
},
data: [0],
},
{
//绿1
name: 'ring5',
type: 'custom',
coordinateSystem: 'none',
renderItem: function (params, api) {
let x0 = api.getWidth() / 3
let y0 = api.getHeight() / 2
let r = (Math.min(api.getWidth(), api.getHeight()) / 2) * 0.65
let point = getCirlPoint(x0, y0, r, 90 + -angle)
return {
type: 'circle',
shape: {
cx: point.x,
cy: point.y,
r: 4,
},
style: {
stroke: '#66FFFF', //
fill: '#66FFFF',
},
silent: true,
}
},
data: [0],
},
{
//绿2
name: 'ring5', //绿
type: 'custom',
coordinateSystem: 'none',
renderItem: function (params, api) {
let x0 = api.getWidth() / 3
let y0 = api.getHeight() / 2
let r = (Math.min(api.getWidth(), api.getHeight()) / 2) * 0.65
let point = getCirlPoint(x0, y0, r, 270 + -angle)
return {
type: 'circle',
shape: {
cx: point.x,
cy: point.y,
r: 4,
},
style: {
stroke: '#66FFFF', //
fill: '#66FFFF',
},
silent: true,
}
},
data: [0],
},
{
//绿3
name: 'ring5',
type: 'custom',
coordinateSystem: 'none',
renderItem: function (params, api) {
let x0 = api.getWidth() / 3
let y0 = api.getHeight() / 2
let r = (Math.min(api.getWidth(), api.getHeight()) / 2) * 0.6
let point = getCirlPoint(x0, y0, r, 90 + angle)
return {
type: 'circle',
shape: {
cx: point.x,
cy: point.y,
r: 4,
},
style: {
stroke: '#66FFFF', //
fill: '#66FFFF',
},
silent: true,
}
},
data: [0],
},
{
//绿4
name: 'ring5', //绿
type: 'custom',
coordinateSystem: 'none',
renderItem: function (params, api) {
let x0 = api.getWidth() / 3
let y0 = api.getHeight() / 2
let r = (Math.min(api.getWidth(), api.getHeight()) / 2) * 0.6
let point = getCirlPoint(x0, y0, r, 270 + angle)
return {
type: 'circle',
shape: {
cx: point.x,
cy: point.y,
r: 4,
},
style: {
stroke: '#66FFFF', //
fill: '#66FFFF',
},
silent: true,
}
},
data: [0],
},
{
name: '',
type: 'pie',
clockWise: false,
radius: ['98%', '95%'],
hoverAnimation: false,
center: ['33.33%', '50%'],
top: 'center',
itemStyle: {
normal: {
label: {
show: false,
},
},
},
data: data,
},
{
type: 'pie',
top: 'center',
startAngle: 90,
clockwise: false,
center: ['33.33%', '50%'],
legendHoverLink: false,
hoverAnimation: false,
radius: ['94%', '55%'],
itemStyle: {
opacity: 0.15,
},
label: {
show: false,
position: 'center',
},
labelLine: {
show: false,
},
data: data2,
},
{
name: '',
type: 'pie',
clockWise: false,
center: ['33.33%', '50%'],
radius: ['39%', '38%'],
hoverAnimation: false,
top: 'center',
itemStyle: {
normal: {
label: {
show: false,
},
},
},
data: data,
},
],
}
//(x0,y0rangle)
function getCirlPoint(x0, y0, r, angle) {
let x1 = x0 + r * Math.cos((angle * Math.PI) / 180)
let y1 = y0 + r * Math.sin((angle * Math.PI) / 180)
return {
x: x1,
y: y1,
}
}
onMounted(()=>{
chart = initChart()
setInterval(function() {
//setInterval
let chart: EChartsType
const initChart = () => {
let chart = echarts.init(document.getElementById(props.id))
draw(chart)
}, 100);
return chart
}
function draw(chart) {
angle = angle + 3
chart.setOption(option, true)
//window.requestAnimationFrame(draw);
}
window.addEventListener('resize',function (){
chart&&chart.resize()
onMounted(() => {
chart = initChart()
setInterval(function () {
//setInterval
draw(chart)
}, 100)
window.addEventListener('resize', function () {
chart && chart.resize()
})
})
})
</script>

View File

@ -1,337 +1,338 @@
<template>
<div :id="id" :class="className" :style="{height:height,width:width}" />
<div :id="id" :class="className" :style="{ height: height, width: width }" />
</template>
<script lang="ts" setup>
import * as echarts from "echarts";
import {EChartsType} from "echarts/core";
import {onMounted} from "vue";
import * as echarts from 'echarts'
import { EChartsType } from 'echarts/core'
import { onMounted } from 'vue'
let props = defineProps({
className: {
type: String,
default: 'chart'
},
config:{
type: Object,
default: ()=>{}
},
id: {
type: String,
default: 'chart'
},
width: {
type: String,
default: '200px'
},
height: {
type: String,
default: '200px'
}
})
let datalist = [
{
name: "公共平台"
},
{
name: "系统0000"
},
{
name: "系统0011"
},
{
name: "系统0022"
},
{
name: "系统0033"
},
{
name: "系统0044"
},
{
name: "系统0055"
},{
name: "系统11"
},
{
name: "系统22"
},
{
name: "系统33"
},
{
name: "系统44"
},
{
name: "系统55"
},
{
name: "系统66"
},
{
name: "系统77"
},
{
name: "系统88"
},
{
name: "系统99"
}
];
let linksData = [
{
source: "公共平台",
target: "系统0000",
value: 1044305
},
{
source: "公共平台",
target: "系统0011",
value: 651527
},
{
source: "公共平台",
target: "系统0022",
value: 651527
},
{
source: "公共平台",
target: "系统0033",
value: 486710
},
{
source: "公共平台",
target: "系统0044",
value: 212670
},
{
source: "公共平台",
target: "系统0055",
value: 210400
},{
source: "系统0011",
target: "系统11",
value: 645246
},
{
source: "系统0022",
target: "系统22",
value: 513275
},
{
source: "系统0011",
target: "系统33",
value: 282986
},
{
source: "系统0011",
target: "系统44",
value: 118655
},
{
source: "系统0022",
target: "系统55",
value: 105989
},
{
source: "系统0022",
target: "系统66",
value: 95100
},
{
source: "系统0033",
target: "系统77",
value: 87796
},
{
source: "系统0044",
target: "系统88",
value: 47658
},
{
source: "系统0055",
target: "系统99",
value: 243660
},
];
let Color = [
"#61FEFF",
"#937FE6",
"#2B56D3",
"#87E7AA",
"#937FE6",
"#FF9B97",
"#8f23f5",
"#0576ea",
"#2cb8cf",
"#8A7EE0",
"#2cb8cf",
"#4e70f0",
"#1fa3de",
"#bbc951",
"#FFC14B",
"#b785a6",
]; let Color1 = [
"#04E0F3",
"#682EFC",
"#35A7FE",
"#0DC09F",
"#682EFC",
"#ED6663",
"#8f23f5",
"#0576ea",
"#2cb8cf",
"#8A7EE0",
"#2cb8cf",
"#4e70f0",
"#1fa3de",
"#bbc951",
"#FFC14B",
"#b785a6",
];
let sourceLabel = [
"right",
"left",
"left",
"left",
"left",
"left",
"left",
"left",
"left",
"left",
"left",
"left",
"left",
"left",
"left",
"left"
];
let itemStyleColor = [];
let labelSource = [];
for (let i = 0; i < datalist.length; i++) {
datalist[i].label = {
normal: {
position: sourceLabel[i]
}
};
labelSource.push(sourceLabel[i]);
}
for (let d = 0; d < datalist.length; d++) {
datalist[d].itemStyle = {
normal: {
// color: Color[d]
color: {
type: "linear",
x: 0,
y: 1,
x2: 0,
y2: 0,
colorStops: [
{
offset: 1,
color: Color[d], // 0%
},
{
offset: 0,
color: Color1[d], // 100%
},
],
global: false, // false
let props = defineProps({
className: {
type: String,
default: 'chart',
},
config: {
type: Object,
default: () => {},
},
id: {
type: String,
default: 'chart',
},
width: {
type: String,
default: '200px',
},
height: {
type: String,
default: '200px',
},
})
let datalist = [
{
name: '公共平台',
},
{
name: '系统0000',
},
{
name: '系统0011',
},
{
name: '系统0022',
},
{
name: '系统0033',
},
{
name: '系统0044',
},
{
name: '系统0055',
},
{
name: '系统11',
},
{
name: '系统22',
},
{
name: '系统33',
},
{
name: '系统44',
},
{
name: '系统55',
},
{
name: '系统66',
},
{
name: '系统77',
},
{
name: '系统88',
},
{
name: '系统99',
},
]
let linksData = [
{
source: '公共平台',
target: '系统0000',
value: 1044305,
},
{
source: '公共平台',
target: '系统0011',
value: 651527,
},
{
source: '公共平台',
target: '系统0022',
value: 651527,
},
{
source: '公共平台',
target: '系统0033',
value: 486710,
},
{
source: '公共平台',
target: '系统0044',
value: 212670,
},
{
source: '公共平台',
target: '系统0055',
value: 210400,
},
{
source: '系统0011',
target: '系统11',
value: 645246,
},
{
source: '系统0022',
target: '系统22',
value: 513275,
},
{
source: '系统0011',
target: '系统33',
value: 282986,
},
{
source: '系统0011',
target: '系统44',
value: 118655,
},
{
source: '系统0022',
target: '系统55',
value: 105989,
},
{
source: '系统0022',
target: '系统66',
value: 95100,
},
{
source: '系统0033',
target: '系统77',
value: 87796,
},
{
source: '系统0044',
target: '系统88',
value: 47658,
},
{
source: '系统0055',
target: '系统99',
value: 243660,
},
]
let Color = [
'#61FEFF',
'#937FE6',
'#2B56D3',
'#87E7AA',
'#937FE6',
'#FF9B97',
'#8f23f5',
'#0576ea',
'#2cb8cf',
'#8A7EE0',
'#2cb8cf',
'#4e70f0',
'#1fa3de',
'#bbc951',
'#FFC14B',
'#b785a6',
]
let Color1 = [
'#04E0F3',
'#682EFC',
'#35A7FE',
'#0DC09F',
'#682EFC',
'#ED6663',
'#8f23f5',
'#0576ea',
'#2cb8cf',
'#8A7EE0',
'#2cb8cf',
'#4e70f0',
'#1fa3de',
'#bbc951',
'#FFC14B',
'#b785a6',
]
let sourceLabel = [
'right',
'left',
'left',
'left',
'left',
'left',
'left',
'left',
'left',
'left',
'left',
'left',
'left',
'left',
'left',
'left',
]
let itemStyleColor = []
let labelSource = []
for (let i = 0; i < datalist.length; i++) {
datalist[i].label = {
normal: {
position: sourceLabel[i],
},
}
};
itemStyleColor.push(datalist[d]);
}
const options = {
backgroundColor: "#031d7a",
tooltip: {
trigger: "item",
triggerOn: "mousemove",
formatter: function(params) {
if (params.name == "公共平台") {
return " 公共平台 "
} else {
let value = params.data.value;
if (!value && value !== 0) return 0;
let str = value.toString();
let reg = str.indexOf(".") > -1 ? /(\d)(?=(\d{3})+\.)/g : /(\d)(?=(?:\d{3})+$)/g;
if (params.data.source == "公共平台") {
return params.data.target + " : " + str.replace(reg, "$1,");
} else {
return params.data.source + " : " + str.replace(reg, "$1,");
}
}
}
},
series: [{
type: "sankey",
layout: "none",
top: "4%",
bottom: "12%",
left: "20",
right: "20",
nodeGap: 15,
nodeWidth: 25,
focusNodeAdjacency: "allEdges",
data: itemStyleColor,
links: linksData,
label: {
labelSource.push(sourceLabel[i])
}
for (let d = 0; d < datalist.length; d++) {
datalist[d].itemStyle = {
normal: {
color: "#fff",
fontSize: 14,
formatter: function(params) {
if (params.data.name == '公共平台') {
let strs = params.data.name.split(''); //
let str = ''
for (let i = 0, s; s = strs[i++];) { //
str += s;
if (!(i % 1)) str += '\n'; //
}
return "{white|" + str + "}"
} else {
return params.data.name
}
// color: Color[d]
color: {
type: 'linear',
x: 0,
y: 1,
x2: 0,
y2: 0,
colorStops: [
{
offset: 1,
color: Color[d], // 0%
},
{
offset: 0,
color: Color1[d], // 100%
},
],
global: false, // false
},
rich: {
white: {
fontSize: 16,
lineHeight: 30,
padding: [0, 0, 0, -26]
},
}
itemStyleColor.push(datalist[d])
}
const options = {
backgroundColor: '#031d7a',
tooltip: {
trigger: 'item',
triggerOn: 'mousemove',
formatter: function (params) {
if (params.name == '公共平台') {
return ' 公共平台 '
} else {
let value = params.data.value
if (!value && value !== 0) return 0
let str = value.toString()
let reg = str.indexOf('.') > -1 ? /(\d)(?=(\d{3})+\.)/g : /(\d)(?=(?:\d{3})+$)/g
if (params.data.source == '公共平台') {
return params.data.target + ' : ' + str.replace(reg, '$1,')
} else {
return params.data.source + ' : ' + str.replace(reg, '$1,')
}
}
}
},
},
lineStyle: {
normal: {
opacity: 0.4,
color: "source",
curveness: 0.5
}
},
itemStyle: {
normal: {
borderWidth: 1,
borderColor: "transparent"
}
}
}]
};
let chart:EChartsType;
const initChart =()=> {
let chart = echarts.init(document.getElementById(props.id))
chart.setOption(options)
return chart
}
onMounted(()=>{
chart = initChart()
window.addEventListener('resize',function (){
chart&&chart.resize()
series: [
{
type: 'sankey',
layout: 'none',
top: '4%',
bottom: '12%',
left: '20',
right: '20',
nodeGap: 15,
nodeWidth: 25,
focusNodeAdjacency: 'allEdges',
data: itemStyleColor,
links: linksData,
label: {
normal: {
color: '#fff',
fontSize: 14,
formatter: function (params) {
if (params.data.name == '公共平台') {
let strs = params.data.name.split('') //
let str = ''
for (let i = 0, s; (s = strs[i++]); ) {
//
str += s
if (!(i % 1)) str += '\n' //
}
return '{white|' + str + '}'
} else {
return params.data.name
}
},
rich: {
white: {
fontSize: 16,
lineHeight: 30,
padding: [0, 0, 0, -26],
},
},
},
},
lineStyle: {
normal: {
opacity: 0.4,
color: 'source',
curveness: 0.5,
},
},
itemStyle: {
normal: {
borderWidth: 1,
borderColor: 'transparent',
},
},
},
],
}
let chart: EChartsType
const initChart = () => {
let chart = echarts.init(document.getElementById(props.id))
chart.setOption(options)
return chart
}
onMounted(() => {
chart = initChart()
window.addEventListener('resize', function () {
chart && chart.resize()
})
})
})
</script>

View File

@ -1,40 +1,38 @@
export const cityIconData = [
{
adcode: 650000,
name: "新疆维吾尔自治区",
value:[88.999903,43.607078]
},{
adcode: 150000,
name: "内蒙古自治区",
value:[119.24787,42.205741]
},
,{
adcode: 150000,
name: "内蒙古自治区",
value:[110.627161,41.16628]
},
{
adcode: 540000,
name: "西藏自治区",
value:[89.483714,30.251951]
},
{
adcode: 630000,
name: "青海省",
value:[102.064693,37.084008]
},
{
adcode: 530000,
name: "云南省",
value:[102.187665,25.083688]
},
{
adcode: 610000,
name: "陕西省",
value:[109.20663,35.018625]
},
{
adcode: 650000,
name: '新疆维吾尔自治区',
value: [88.999903, 43.607078],
},
{
adcode: 150000,
name: '内蒙古自治区',
value: [119.24787, 42.205741],
},
,
{
adcode: 150000,
name: '内蒙古自治区',
value: [110.627161, 41.16628],
},
{
adcode: 540000,
name: '西藏自治区',
value: [89.483714, 30.251951],
},
{
adcode: 630000,
name: '青海省',
value: [102.064693, 37.084008],
},
{
adcode: 530000,
name: '云南省',
value: [102.187665, 25.083688],
},
{
adcode: 610000,
name: '陕西省',
value: [109.20663, 35.018625],
},
]

View File

@ -1,22 +1,214 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports,require("echarts")):"function"==typeof define&&define.amd?define(["exports","echarts"],e):e(t.bmap={},t.echarts)}(this,function(t,e){"use strict";function o(t,e){this._bmap=t,this.dimensions=["lng","lat"],this._mapOffset=[0,0],this._api=e,this._projection=new BMap.MercatorProjection}function n(t,o){return o=o||[0,0],e.util.map([0,1],function(e){var n=o[e],i=t[e]/2,a=[],r=[];return a[e]=n-i,r[e]=n+i,a[1-e]=r[1-e]=o[1-e],Math.abs(this.dataToPoint(a)[e]-this.dataToPoint(r)[e])},this)}function i(){function t(t){this._root=t}return t.prototype=new BMap.Overlay,t.prototype.initialize=function(t){return t.getPanes().labelPane.appendChild(this._root),this._root},t.prototype.draw=function(){},t}function a(t,e){return t&&e&&t[0]===e[0]&&t[1]===e[1]}o.prototype.dimensions=["lng","lat"],o.prototype.setZoom=function(t){this._zoom=t},o.prototype.setCenter=function(t){this._center=this._projection.lngLatToPoint(new BMap.Point(t[0],t[1]))},o.prototype.setMapOffset=function(t){this._mapOffset=t},o.prototype.getBMap=function(){return this._bmap},o.prototype.dataToPoint=function(t){var e=new BMap.Point(t[0],t[1]),o=this._bmap.pointToOverlayPixel(e),n=this._mapOffset;return[o.x-n[0],o.y-n[1]]},o.prototype.pointToData=function(t){var e=this._mapOffset;return[(t=this._bmap.overlayPixelToPoint({x:t[0]+e[0],y:t[1]+e[1]})).lng,t.lat]},o.prototype.getViewRect=function(){var t=this._api;return new e.graphic.BoundingRect(0,0,t.getWidth(),t.getHeight())},o.prototype.getRoamTransform=function(){return e.matrix.create()},o.prototype.prepareCustoms=function(t){var o=this.getViewRect();return{coordSys:{type:"bmap",x:o.x,y:o.y,width:o.width,height:o.height},api:{coord:e.util.bind(this.dataToPoint,this),size:e.util.bind(n,this)}}};var r;o.dimensions=o.prototype.dimensions,o.create=function(t,e){var n,a=e.getDom();t.eachComponent("bmap",function(t){var p=e.getZr().painter,s=p.getViewportRoot();if("undefined"==typeof BMap)throw new Error("BMap api is not loaded");if(r=r||i(),n)throw new Error("Only one bmap component can exist");if(!t.__bmap){var m=a.querySelector(".ec-extension-bmap");m&&(s.style.left="0px",s.style.top="0px",a.removeChild(m)),(m=document.createElement("div")).style.cssText="width:100%;height:100%",m.classList.add("ec-extension-bmap"),a.appendChild(m);var c=t.__bmap=new BMap.Map(m),d=new r(s);c.addOverlay(d),p.getViewportRootOffset=function(){return{offsetLeft:0,offsetTop:0}}}var c=t.__bmap,f=t.get("center"),l=t.get("zoom");if(f&&l){var h=new BMap.Point(f[0],f[1]);c.centerAndZoom(h,l)}(n=new o(c,e)).setMapOffset(t.__mapOffset||[0,0]),n.setZoom(l),n.setCenter(f),t.coordinateSystem=n}),t.eachSeries(function(t){"bmap"===t.get("coordinateSystem")&&(t.coordinateSystem=n)})},e.extendComponentModel({type:"bmap",getBMap:function(){return this.__bmap},setCenterAndZoom:function(t,e){this.option.center=t,this.option.zoom=e},centerOrZoomChanged:function(t,e){var o=this.option;return!(a(t,o.center)&&e===o.zoom)},defaultOption:{center:[104.114129,37.550339],zoom:5,mapStyle:{},roam:!1}}),e.extendComponentView({type:"bmap",render:function(t,e,o){function n(){i||o.dispatchAction({type:"bmapRoam"})}var i=!0,a=t.getBMap(),r=o.getZr().painter.getViewportRoot(),p=t.coordinateSystem,s=function(e,n){if(!i){var a=r.parentNode.parentNode.parentNode,s=[-parseInt(a.style.left,10)||0,-parseInt(a.style.top,10)||0];r.style.left=s[0]+"px",r.style.top=s[1]+"px",p.setMapOffset(s),t.__mapOffset=s,o.dispatchAction({type:"bmapRoam"})}};a.removeEventListener("moving",this._oldMoveHandler),a.removeEventListener("zoomend",this._oldZoomEndHandler),a.addEventListener("moving",s),a.addEventListener("zoomend",n),this._oldMoveHandler=s,this._oldZoomEndHandler=n;var m=t.get("roam");m&&"scale"!==m?a.enableDragging():a.disableDragging(),m&&"move"!==m?(a.enableScrollWheelZoom(),a.enableDoubleClickZoom(),a.enablePinchToZoom()):(a.disableScrollWheelZoom(),a.disableDoubleClickZoom(),a.disablePinchToZoom());var c=t.__mapStyle,d=t.get("mapStyle")||{},f=JSON.stringify(d);JSON.stringify(c)!==f&&(Object.keys(d).length&&a.setMapStyle(d),t.__mapStyle=JSON.parse(f)),i=!1}}),e.registerCoordinateSystem("bmap",o),e.registerAction({type:"bmapRoam",event:"bmapRoam",update:"updateLayout"},function(t,e){e.eachComponent("bmap",function(t){var e=t.getBMap(),o=e.getCenter();t.setCenterAndZoom([o.lng,o.lat],e.getZoom())})});t.version="1.0.0"});
!(function (t, e) {
'object' == typeof exports && 'undefined' != typeof module
? e(exports, require('echarts'))
: 'function' == typeof define && define.amd
? define(['exports', 'echarts'], e)
: e((t.bmap = {}), t.echarts)
})(this, function (t, e) {
'use strict'
function o(t, e) {
;(this._bmap = t),
(this.dimensions = ['lng', 'lat']),
(this._mapOffset = [0, 0]),
(this._api = e),
(this._projection = new BMap.MercatorProjection())
}
function n(t, o) {
return (
(o = o || [0, 0]),
e.util.map(
[0, 1],
function (e) {
var n = o[e],
i = t[e] / 2,
a = [],
r = []
return (
(a[e] = n - i),
(r[e] = n + i),
(a[1 - e] = r[1 - e] = o[1 - e]),
Math.abs(this.dataToPoint(a)[e] - this.dataToPoint(r)[e])
)
},
this,
)
)
}
function i() {
function t(t) {
this._root = t
}
return (
(t.prototype = new BMap.Overlay()),
(t.prototype.initialize = function (t) {
return t.getPanes().labelPane.appendChild(this._root), this._root
}),
(t.prototype.draw = function () {}),
t
)
}
function a(t, e) {
return t && e && t[0] === e[0] && t[1] === e[1]
}
;(o.prototype.dimensions = ['lng', 'lat']),
(o.prototype.setZoom = function (t) {
this._zoom = t
}),
(o.prototype.setCenter = function (t) {
this._center = this._projection.lngLatToPoint(new BMap.Point(t[0], t[1]))
}),
(o.prototype.setMapOffset = function (t) {
this._mapOffset = t
}),
(o.prototype.getBMap = function () {
return this._bmap
}),
(o.prototype.dataToPoint = function (t) {
var e = new BMap.Point(t[0], t[1]),
o = this._bmap.pointToOverlayPixel(e),
n = this._mapOffset
return [o.x - n[0], o.y - n[1]]
}),
(o.prototype.pointToData = function (t) {
var e = this._mapOffset
return [(t = this._bmap.overlayPixelToPoint({ x: t[0] + e[0], y: t[1] + e[1] })).lng, t.lat]
}),
(o.prototype.getViewRect = function () {
var t = this._api
return new e.graphic.BoundingRect(0, 0, t.getWidth(), t.getHeight())
}),
(o.prototype.getRoamTransform = function () {
return e.matrix.create()
}),
(o.prototype.prepareCustoms = function (t) {
var o = this.getViewRect()
return {
coordSys: { type: 'bmap', x: o.x, y: o.y, width: o.width, height: o.height },
api: { coord: e.util.bind(this.dataToPoint, this), size: e.util.bind(n, this) },
}
})
var r
;(o.dimensions = o.prototype.dimensions),
(o.create = function (t, e) {
var n,
a = e.getDom()
t.eachComponent('bmap', function (t) {
var p = e.getZr().painter,
s = p.getViewportRoot()
if ('undefined' == typeof BMap) throw new Error('BMap api is not loaded')
if (((r = r || i()), n)) throw new Error('Only one bmap component can exist')
if (!t.__bmap) {
var m = a.querySelector('.ec-extension-bmap')
m && ((s.style.left = '0px'), (s.style.top = '0px'), a.removeChild(m)),
((m = document.createElement('div')).style.cssText = 'width:100%;height:100%'),
m.classList.add('ec-extension-bmap'),
a.appendChild(m)
var c = (t.__bmap = new BMap.Map(m)),
d = new r(s)
c.addOverlay(d),
(p.getViewportRootOffset = function () {
return { offsetLeft: 0, offsetTop: 0 }
})
}
var c = t.__bmap,
f = t.get('center'),
l = t.get('zoom')
if (f && l) {
var h = new BMap.Point(f[0], f[1])
c.centerAndZoom(h, l)
}
;(n = new o(c, e)).setMapOffset(t.__mapOffset || [0, 0]),
n.setZoom(l),
n.setCenter(f),
(t.coordinateSystem = n)
}),
t.eachSeries(function (t) {
'bmap' === t.get('coordinateSystem') && (t.coordinateSystem = n)
})
}),
e.extendComponentModel({
type: 'bmap',
getBMap: function () {
return this.__bmap
},
setCenterAndZoom: function (t, e) {
;(this.option.center = t), (this.option.zoom = e)
},
centerOrZoomChanged: function (t, e) {
var o = this.option
return !(a(t, o.center) && e === o.zoom)
},
defaultOption: { center: [104.114129, 37.550339], zoom: 5, mapStyle: {}, roam: !1 },
}),
e.extendComponentView({
type: 'bmap',
render: function (t, e, o) {
function n() {
i || o.dispatchAction({ type: 'bmapRoam' })
}
var i = !0,
a = t.getBMap(),
r = o.getZr().painter.getViewportRoot(),
p = t.coordinateSystem,
s = function (e, n) {
if (!i) {
var a = r.parentNode.parentNode.parentNode,
s = [-parseInt(a.style.left, 10) || 0, -parseInt(a.style.top, 10) || 0]
;(r.style.left = s[0] + 'px'),
(r.style.top = s[1] + 'px'),
p.setMapOffset(s),
(t.__mapOffset = s),
o.dispatchAction({ type: 'bmapRoam' })
}
}
a.removeEventListener('moving', this._oldMoveHandler),
a.removeEventListener('zoomend', this._oldZoomEndHandler),
a.addEventListener('moving', s),
a.addEventListener('zoomend', n),
(this._oldMoveHandler = s),
(this._oldZoomEndHandler = n)
var m = t.get('roam')
m && 'scale' !== m ? a.enableDragging() : a.disableDragging(),
m && 'move' !== m
? (a.enableScrollWheelZoom(), a.enableDoubleClickZoom(), a.enablePinchToZoom())
: (a.disableScrollWheelZoom(), a.disableDoubleClickZoom(), a.disablePinchToZoom())
var c = t.__mapStyle,
d = t.get('mapStyle') || {},
f = JSON.stringify(d)
JSON.stringify(c) !== f &&
(Object.keys(d).length && a.setMapStyle(d), (t.__mapStyle = JSON.parse(f))),
(i = !1)
},
}),
e.registerCoordinateSystem('bmap', o),
e.registerAction(
{ type: 'bmapRoam', event: 'bmapRoam', update: 'updateLayout' },
function (t, e) {
e.eachComponent('bmap', function (t) {
var e = t.getBMap(),
o = e.getCenter()
t.setCenterAndZoom([o.lng, o.lat], e.getZoom())
})
},
)
t.version = '1.0.0'
})

File diff suppressed because one or more lines are too long

View File

@ -1,289 +1,290 @@
<template>
<div :id="id" :class="className" :style="{height:height,width:width}" />
<div :id="id" :class="className" :style="{ height: height, width: width }" />
</template>
<script lang="ts" setup>
import 'echarts-liquidfill/src/liquidFill.js'
import './china.js'
import './bmap.min.js'
import * as echarts from "echarts";
import {EChartsType} from "echarts/core";
import {onMounted} from "vue";
import 'echarts-liquidfill/src/liquidFill.js'
import './china.js'
import './bmap.min.js'
import * as echarts from 'echarts'
import { EChartsType } from 'echarts/core'
import { onMounted } from 'vue'
let props = defineProps({
className: {
type: String,
default: 'chart'
},
config:{
type: Object,
default: ()=>{}
},
id: {
type: String,
default: 'chart'
},
width: {
type: String,
default: '200px'
},
height: {
type: String,
default: '200px'
}
})
//
var geoCoordMap = {
"北京": [116.46, 39.92],
"成都": [104.06, 30.67],
"杭州": [120.19, 30.26],
"济南": [117, 36.65],
"福州": [119.3, 26.08],
"上海": [121.48, 31.22],
"重庆": [106.54, 29.59],
"深圳": [114.07, 22.62],
"宁波": [121.56, 29.86],
"南昌": [115.89, 28.68],
"广州": [113.23, 23.16],
"厦门": [118.1, 24.46],
"太原": [112.53, 37.87],
"哈尔滨": [126.63, 45.75],
"西安": [108.95, 34.27],
"沈阳": [123.38, 41.8],
"大连": [121.62, 38.92],
"海口": [110.35, 20.02],
"长沙": [113, 28.21],
"银川": [106.27, 38.47],
"石家庄": [114.48, 38.03],
"昆明": [102.73, 25.04],
"武汉": [114.31, 30.52],
"呼和浩特": [111.65, 40.82],
"天津": [117.2, 39.13],
"贵阳": [106.71, 26.57],
"兰州": [103.73, 36.03],
"青岛": [120.33, 36.07],
"南京": [118.78, 32.04],
"长春": [125.35, 43.88],
"郑州": [113.65, 34.76],
"西宁": [101.74, 36.56],
"合肥": [117.27, 31.86],
"南宁": [108.33, 22.84],
"拉萨": [91.11, 29.97],
"乌鲁木齐": [87.68, 43.77]
};
//
var data = [
{name:"北京",value:88.8},
{name:"成都",value:88.7},
{name:"厦门",value:88.01},
{name:"杭州",value:87.9},
{name:"济南",value:87.48},
{name:"福州",value:87.47},
{name:"上海",value:87.43},
{name:"重庆",value:87.38},
{name:"深圳",value:87.37},
{name:"昆明",value:87.26},
{name:"宁波",value:87.1},
{name:"南昌",value:86.06},
{name:"广州",value:85.89},
{name:"太原",value:84.45},
{name:"哈尔滨",value:83.96},
{name:"西安",value:83.24},
{name:"沈阳",value:82.96},
{name:"大连",value:82.94},
{name:"海口",value:82.88},
{name:"长沙",value:82.85},
{name:"银川",value:82.49},
{name:"石家庄",value:82.24},
{name:"武汉",value:81.68},
{name:"呼和浩特",value:81.61},
{name:"天津",value:80.99},
{name:"贵阳",value:80.71},
{name:"兰州",value:80.69},
{name:"南京",value:80.65},
{name:"青岛",value:80.61},
{name:"长春",value:80.1},
{name:"郑州",value:79.56},
{name:"西宁",value:79.07},
{name:"南宁",value:78.2},
{name:"合肥",value:77.29},
{name:"乌鲁木齐",value:76.91},
{name:"拉萨",value:76.01}
];
var convertData = function(data) {
var res = [];
for (var i = 0; i < data.length; i++) {
var geoCoord = geoCoordMap[data[i].name];
if (geoCoord) {
res.push({
name: data[i].name,
value: geoCoord.concat(data[i].value)
});
}
}
return res;
};
const options = {
toolbox: {
show: true,
feature: {
dataView: {
show: true,
readOnly: true
},
restore: {
show: true
},
saveAsImage: {
show: true
}
let props = defineProps({
className: {
type: String,
default: 'chart',
},
top:40,
right:40
},
title: {
//text: '2020',
top:40,
//subtext: 'from ',
left: 'center',
textStyle: {
color: '#ffffff',
fontSize: 30
config: {
type: Object,
default: () => {},
},
subtextStyle: {
fontSize: 20
}
},
legend: {
left: 'left',
data: ['强', '中', '弱'],
textStyle: {
color: '#ccc'
}
},
backgroundColor: {
type: 'linear',
x: 0,
y: 0,
x2: 1,
y2: 1,
colorStops: [{
offset: 0, color: '#0f2c70' // 0%
}, {
offset: 1, color: '#091732' // 100%
}],
globalCoord: false // false
},
visualMap: {
min: 75,
max: 90,
left: 40,
bottom: 40,
calculable: false,
text: ['高', '低'],
inRange: {
color: ['rgb(4, 1, 255)', 'rgb(225, 1, 255)']
id: {
type: String,
default: 'chart',
},
textStyle: {
color: '#ffffff',
fontSize: 10
}
},
geo: {
map: 'china',
show: true,
roam: true,
label: {
emphasis: {
show: true
}
width: {
type: String,
default: '200px',
},
itemStyle: {
normal: {
areaColor: '#091632',
borderColor: '#1773c3',
shadowColor: '#1773c3',
shadowBlur: 20
}
}
},
series: [
{
type: 'map',
map: 'china',
geoIndex: 1,
aspectScale: 0.75, //
showLegendSymbol: true, // legend
label: {
normal: {
show: false,
},
emphasis: {
show: false,
textStyle: {
color: '#fff'
}
}
},
roam: true,
itemStyle: {
normal: {
areaColor: '#031525',
borderColor: '#3B5077',
borderWidth: 1.5
},
emphasis: {
areaColor: '#0f2c70'
}
},
height: {
type: String,
default: '200px',
},
{
name: '城市',
type: 'scatter',
coordinateSystem: 'geo',
data: convertData(data),
symbolSize: function (val) {
return val[2]/8;
},
label: {
normal: {
formatter: '{b}',
position: 'bottom',
textStyle:{
fontSize:10,
fontWeight:'bolder',
color:'#ffffff'
},
show: true
},
emphasis: {
show: true
}
},
itemStyle: {
normal: {
color: '#ddb926'
}
}
}
]
};
let chart:EChartsType;
const initChart =()=> {
let chart = echarts.init(document.getElementById(props.id))
chart.setOption(options)
return chart
}
onMounted(()=>{
chart = initChart()
window.addEventListener('resize',function (){
chart&&chart.resize()
})
})
//
var geoCoordMap = {
北京: [116.46, 39.92],
成都: [104.06, 30.67],
杭州: [120.19, 30.26],
济南: [117, 36.65],
福州: [119.3, 26.08],
上海: [121.48, 31.22],
重庆: [106.54, 29.59],
深圳: [114.07, 22.62],
宁波: [121.56, 29.86],
南昌: [115.89, 28.68],
广州: [113.23, 23.16],
厦门: [118.1, 24.46],
太原: [112.53, 37.87],
哈尔滨: [126.63, 45.75],
西安: [108.95, 34.27],
沈阳: [123.38, 41.8],
大连: [121.62, 38.92],
海口: [110.35, 20.02],
长沙: [113, 28.21],
银川: [106.27, 38.47],
石家庄: [114.48, 38.03],
昆明: [102.73, 25.04],
武汉: [114.31, 30.52],
呼和浩特: [111.65, 40.82],
天津: [117.2, 39.13],
贵阳: [106.71, 26.57],
兰州: [103.73, 36.03],
青岛: [120.33, 36.07],
南京: [118.78, 32.04],
长春: [125.35, 43.88],
郑州: [113.65, 34.76],
西宁: [101.74, 36.56],
合肥: [117.27, 31.86],
南宁: [108.33, 22.84],
拉萨: [91.11, 29.97],
乌鲁木齐: [87.68, 43.77],
}
//
var data = [
{ name: '北京', value: 88.8 },
{ name: '成都', value: 88.7 },
{ name: '厦门', value: 88.01 },
{ name: '杭州', value: 87.9 },
{ name: '济南', value: 87.48 },
{ name: '福州', value: 87.47 },
{ name: '上海', value: 87.43 },
{ name: '重庆', value: 87.38 },
{ name: '深圳', value: 87.37 },
{ name: '昆明', value: 87.26 },
{ name: '宁波', value: 87.1 },
{ name: '南昌', value: 86.06 },
{ name: '广州', value: 85.89 },
{ name: '太原', value: 84.45 },
{ name: '哈尔滨', value: 83.96 },
{ name: '西安', value: 83.24 },
{ name: '沈阳', value: 82.96 },
{ name: '大连', value: 82.94 },
{ name: '海口', value: 82.88 },
{ name: '长沙', value: 82.85 },
{ name: '银川', value: 82.49 },
{ name: '石家庄', value: 82.24 },
{ name: '武汉', value: 81.68 },
{ name: '呼和浩特', value: 81.61 },
{ name: '天津', value: 80.99 },
{ name: '贵阳', value: 80.71 },
{ name: '兰州', value: 80.69 },
{ name: '南京', value: 80.65 },
{ name: '青岛', value: 80.61 },
{ name: '长春', value: 80.1 },
{ name: '郑州', value: 79.56 },
{ name: '西宁', value: 79.07 },
{ name: '南宁', value: 78.2 },
{ name: '合肥', value: 77.29 },
{ name: '乌鲁木齐', value: 76.91 },
{ name: '拉萨', value: 76.01 },
]
var convertData = function (data) {
var res = []
for (var i = 0; i < data.length; i++) {
var geoCoord = geoCoordMap[data[i].name]
if (geoCoord) {
res.push({
name: data[i].name,
value: geoCoord.concat(data[i].value),
})
}
}
return res
}
const options = {
toolbox: {
show: true,
feature: {
dataView: {
show: true,
readOnly: true,
},
restore: {
show: true,
},
saveAsImage: {
show: true,
},
},
top: 40,
right: 40,
},
title: {
//text: '2020',
top: 40,
//subtext: 'from ',
left: 'center',
textStyle: {
color: '#ffffff',
fontSize: 30,
},
subtextStyle: {
fontSize: 20,
},
},
legend: {
left: 'left',
data: ['强', '中', '弱'],
textStyle: {
color: '#ccc',
},
},
backgroundColor: {
type: 'linear',
x: 0,
y: 0,
x2: 1,
y2: 1,
colorStops: [
{
offset: 0,
color: '#0f2c70', // 0%
},
{
offset: 1,
color: '#091732', // 100%
},
],
globalCoord: false, // false
},
visualMap: {
min: 75,
max: 90,
left: 40,
bottom: 40,
calculable: false,
text: ['高', '低'],
inRange: {
color: ['rgb(4, 1, 255)', 'rgb(225, 1, 255)'],
},
textStyle: {
color: '#ffffff',
fontSize: 10,
},
},
geo: {
map: 'china',
show: true,
roam: true,
label: {
emphasis: {
show: true,
},
},
itemStyle: {
normal: {
areaColor: '#091632',
borderColor: '#1773c3',
shadowColor: '#1773c3',
shadowBlur: 20,
},
},
},
series: [
{
type: 'map',
map: 'china',
geoIndex: 1,
aspectScale: 0.75, //
showLegendSymbol: true, // legend
label: {
normal: {
show: false,
},
emphasis: {
show: false,
textStyle: {
color: '#fff',
},
},
},
roam: true,
itemStyle: {
normal: {
areaColor: '#031525',
borderColor: '#3B5077',
borderWidth: 1.5,
},
emphasis: {
areaColor: '#0f2c70',
},
},
},
{
name: '城市',
type: 'scatter',
coordinateSystem: 'geo',
data: convertData(data),
symbolSize: function (val) {
return val[2] / 8
},
label: {
normal: {
formatter: '{b}',
position: 'bottom',
textStyle: {
fontSize: 10,
fontWeight: 'bolder',
color: '#ffffff',
},
show: true,
},
emphasis: {
show: true,
},
},
itemStyle: {
normal: {
color: '#ddb926',
},
},
},
],
}
let chart: EChartsType
const initChart = () => {
let chart = echarts.init(document.getElementById(props.id))
chart.setOption(options)
return chart
}
onMounted(() => {
chart = initChart()
window.addEventListener('resize', function () {
chart && chart.resize()
})
})
</script>

File diff suppressed because one or more lines are too long

View File

@ -1,292 +1,302 @@
<template>
<div :id="id" :class="className" :style="{height:height,width:width}" />
<div :id="id" :class="className" :style="{ height: height, width: width }" />
</template>
<script lang="ts" setup>
import { geoJson } from './get.js'
import * as echarts from 'echarts'
import { EChartsType } from 'echarts/core'
import { onMounted } from 'vue'
import {cityIconData} from '../js/data.js'
import logo from '@/assets/logo.png'
const props = defineProps({
className: {
type: String,
default: 'chart'
},
config: {
type: Object,
default: () => {}
},
id: {
type: String,
default: 'chart'
},
width: {
type: String,
default: '200px'
},
height: {
type: String,
default: '200px'
}
})
var geoGpsMap = [109.1162, 34.2004]
var geoCoordMap = {
江苏: [118.8062, 31.9208],
内蒙古: [110.3467, 41.4899],
辽宁: [123.1238, 42.1216],
陕西: [109.1162, 34.2004],
甘肃: [103.5901, 36.3043],
青海: [101.4038, 36.8207],
新疆: [87.9236, 43.5883],
河南: [113.4668, 34.6234],
西藏: [116.3896, 39.91],
浙江: [119.5313, 29.8773],
福建: [119.4543, 25.9222],
湖南: [113.0823, 28.2568],
四川: [113.0823, 28.2568],
云南: [102.9199, 25.4663],
广东: [113.12244, 23.009505],
海南: [110.3893, 19.8516]
}
var value = {
江苏: 10000,
内蒙古: 10000,
辽宁: 10000,
陕西: 10000,
福建: 10000,
甘肃: 10000,
青海: 10000,
新疆: 10000,
湖北: 10000,
浙江: 10000,
河南: 10000,
湖南: 10000,
云南: 10000,
广东: 10000,
海南: 10000,
西藏: 10000
}
var colors = '#f9b207'
var year = ['长春', '长春', '青岛', '青岛', '成都', '成都']
var mapData = []
/* 柱子Y名称 */
var categoryData = []
var barData = []
for (var key in geoCoordMap) {
mapData.push({
year: '陕西',
name: key,
value: value[key] / 100,
value1: value[key] / 100
})
}
mapData.sort(function sortNumber (a, b) {
return a.value - b.value
})
for (var j = 0; j < mapData.length; j++) {
barData.push(mapData[j].value1)
categoryData.push(mapData[j].name)
}
echarts.registerMap('china', geoJson)
var convertData = function (data) {
var res = []
for (var i = 0; i < data.length; i++) {
var geoCoord = geoCoordMap[data[i].name]
if (geoCoord) {
res.push({
name: data[i].name,
value: geoCoord.concat(data[i].value)
})
}
}
return res
}
var convertToLineData = function (data, gps) {
var res = []
for (var i = 0; i < data.length; i++) {
var dataItem = data[i]
var toCoord = geoCoordMap[dataItem.name]
// debugger;
var fromCoord = gps //
// var toCoord = geoGps[Math.random()*3];
if (fromCoord && toCoord) {
res.push([{
coord: fromCoord,
value: dataItem.value
}, {
coord: toCoord
}])
}
}
return res
}
const options = {
tooltip:{
trigger: 'item',
formatter(val){
// console.log('val==========',val)
}
},
backgroundColor: '#001540',
geo: {
show: true,
map: 'china',
roam: true,
zoom: 1,
center: [101.4038, 36.8207],
label: {
emphasis: {
show: false
}
import { geoJson } from './get.js'
import * as echarts from 'echarts'
import { EChartsType } from 'echarts/core'
import { onMounted } from 'vue'
import { cityIconData } from '../js/data.js'
import logo from '@/assets/logo.png'
const props = defineProps({
className: {
type: String,
default: 'chart',
},
itemStyle: {
normal: {
borderColor: 'rgba(147, 235, 248, 1)',
borderWidth: 1,
areaColor: {
type: 'radial',
x: 0.5,
y: 0.5,
r: 0.8,
colorStops: [{
offset: 0,
color: 'rgba(147, 235, 248, 0)' // 0%
}, {
offset: 1,
color: 'rgba(147, 235, 248, .2)' // 100%
}],
globalCoord: false // false
},
shadowColor: 'rgba(128, 217, 248, 1)',
// shadowColor: 'rgba(255, 255, 255, 1)',
shadowOffsetX: -2,
shadowOffsetY: 2,
shadowBlur: 10
},
emphasis: {
areaColor: '#389BB7',
borderWidth: 0
config: {
type: Object,
default: () => {},
},
id: {
type: String,
default: 'chart',
},
width: {
type: String,
default: '200px',
},
height: {
type: String,
default: '200px',
},
})
var geoGpsMap = [109.1162, 34.2004]
var geoCoordMap = {
江苏: [118.8062, 31.9208],
内蒙古: [110.3467, 41.4899],
辽宁: [123.1238, 42.1216],
陕西: [109.1162, 34.2004],
甘肃: [103.5901, 36.3043],
青海: [101.4038, 36.8207],
新疆: [87.9236, 43.5883],
河南: [113.4668, 34.6234],
西藏: [116.3896, 39.91],
浙江: [119.5313, 29.8773],
福建: [119.4543, 25.9222],
湖南: [113.0823, 28.2568],
四川: [113.0823, 28.2568],
云南: [102.9199, 25.4663],
广东: [113.12244, 23.009505],
海南: [110.3893, 19.8516],
}
var value = {
江苏: 10000,
内蒙古: 10000,
辽宁: 10000,
陕西: 10000,
福建: 10000,
甘肃: 10000,
青海: 10000,
新疆: 10000,
湖北: 10000,
浙江: 10000,
河南: 10000,
湖南: 10000,
云南: 10000,
广东: 10000,
海南: 10000,
西藏: 10000,
}
var colors = '#f9b207'
var year = ['长春', '长春', '青岛', '青岛', '成都', '成都']
var mapData = []
/* 柱子Y名称 */
var categoryData = []
var barData = []
for (var key in geoCoordMap) {
mapData.push({
year: '陕西',
name: key,
value: value[key] / 100,
value1: value[key] / 100,
})
}
mapData.sort(function sortNumber(a, b) {
return a.value - b.value
})
for (var j = 0; j < mapData.length; j++) {
barData.push(mapData[j].value1)
categoryData.push(mapData[j].name)
}
echarts.registerMap('china', geoJson)
var convertData = function (data) {
var res = []
for (var i = 0; i < data.length; i++) {
var geoCoord = geoCoordMap[data[i].name]
if (geoCoord) {
res.push({
name: data[i].name,
value: geoCoord.concat(data[i].value),
})
}
}
},
series: [
return res
}
var convertToLineData = function (data, gps) {
var res = []
for (var i = 0; i < data.length; i++) {
var dataItem = data[i]
var toCoord = geoCoordMap[dataItem.name]
// debugger;
var fromCoord = gps //
// var toCoord = geoGps[Math.random()*3];
if (fromCoord && toCoord) {
res.push([
{
coord: fromCoord,
value: dataItem.value,
},
{
coord: toCoord,
},
])
}
}
return res
}
//
{
type: 'map',
const options = {
tooltip: {
trigger: 'item',
formatter(val) {
// console.log('val==========',val)
},
},
backgroundColor: '#001540',
geo: {
show: true,
map: 'china',
geoIndex: 0,
aspectScale: 0.75, //
showLegendSymbol: false, // legend
roam: true,
zoom: 1,
center: [101.4038, 36.8207],
label: {
normal: {
show: false
},
emphasis: {
show: false,
textStyle: {
color: '#fff'
}
}
},
},
roam: true,
itemStyle: {
normal: {
areaColor: '#031525',
borderColor: '#FFFFFF'
borderColor: 'rgba(147, 235, 248, 1)',
borderWidth: 1,
areaColor: {
type: 'radial',
x: 0.5,
y: 0.5,
r: 0.8,
colorStops: [
{
offset: 0,
color: 'rgba(147, 235, 248, 0)', // 0%
},
{
offset: 1,
color: 'rgba(147, 235, 248, .2)', // 100%
},
],
globalCoord: false, // false
},
shadowColor: 'rgba(128, 217, 248, 1)',
// shadowColor: 'rgba(255, 255, 255, 1)',
shadowOffsetX: -2,
shadowOffsetY: 2,
shadowBlur: 10,
},
emphasis: {
areaColor: '#2B91B7'
}
},
animation: false
},
//
{
// name: 'Top 5',
type: 'effectScatter',
coordinateSystem: 'geo',
data: convertData(mapData.sort(function (a, b) {
return b.value - a.value
}).slice(0, 20)),
symbolSize: function (val) {
return val[2] / 10
},
showEffectOn: 'render',
rippleEffect: {
brushType: 'stroke'
},
hoverAnimation: true,
label: {
normal: {
formatter: '{b}',
position: 'right',
show: true
}
},
itemStyle: {
normal: {
color: colors,
shadowBlur: 10,
shadowColor: colors
}
},
zlevel: 1
},
// 线
{
type: 'lines',
zlevel: 2,
effect: {
show: true,
period: 4, //
trailLength: 0.02, // [0,1]
symbol: 'arrow', //
symbolSize: 3 //
},
lineStyle: {
normal: {
color: colors,
width: 0.1, // 线
opacity: 0.5, // 线
curveness: 0.3 // 线
}
},
data: convertToLineData(mapData, geoGpsMap)
},
{
type:'scatter',
zlevel: 16,
coordinateSystem: 'geo',
symbolSize:30,
symbol:`image://${logo}`,
data:cityIconData,
rippleEffect: {
period: 4, brushType: 'stroke', scale: 4
},
tooltip:{
trigger:'item',
padding:0,
borderColor:'black',
background:'rgba(0,0,0,0.7)',
textStyle: {
fontSize:20
areaColor: '#389BB7',
borderWidth: 0,
},
formatter(val){
console.log('val=======',val)
let tipHtml = `
},
},
series: [
//
{
type: 'map',
map: 'china',
geoIndex: 0,
aspectScale: 0.75, //
showLegendSymbol: false, // legend
label: {
normal: {
show: false,
},
emphasis: {
show: false,
textStyle: {
color: '#fff',
},
},
},
roam: true,
itemStyle: {
normal: {
areaColor: '#031525',
borderColor: '#FFFFFF',
},
emphasis: {
areaColor: '#2B91B7',
},
},
animation: false,
},
//
{
// name: 'Top 5',
type: 'effectScatter',
coordinateSystem: 'geo',
data: convertData(
mapData
.sort(function (a, b) {
return b.value - a.value
})
.slice(0, 20),
),
symbolSize: function (val) {
return val[2] / 10
},
showEffectOn: 'render',
rippleEffect: {
brushType: 'stroke',
},
hoverAnimation: true,
label: {
normal: {
formatter: '{b}',
position: 'right',
show: true,
},
},
itemStyle: {
normal: {
color: colors,
shadowBlur: 10,
shadowColor: colors,
},
},
zlevel: 1,
},
// 线
{
type: 'lines',
zlevel: 2,
effect: {
show: true,
period: 4, //
trailLength: 0.02, // [0,1]
symbol: 'arrow', //
symbolSize: 3, //
},
lineStyle: {
normal: {
color: colors,
width: 0.1, // 线
opacity: 0.5, // 线
curveness: 0.3, // 线
},
},
data: convertToLineData(mapData, geoGpsMap),
},
{
type: 'scatter',
zlevel: 16,
coordinateSystem: 'geo',
symbolSize: 30,
symbol: `image://${logo}`,
data: cityIconData,
rippleEffect: {
period: 4,
brushType: 'stroke',
scale: 4,
},
tooltip: {
trigger: 'item',
padding: 0,
borderColor: 'black',
background: 'rgba(0,0,0,0.7)',
textStyle: {
fontSize: 20,
},
formatter(val) {
console.log('val=======', val)
let tipHtml = `
<div class="m-info" style=" opacity: 0.95;background: rgba(25,27,29,1);" >
<div class="title" style="padding-left: 12px;
padding-top: 10px;
@ -296,22 +306,22 @@ const options = {
<!-- <div style=" font-size: 22px; color: #ff0000;">258944</div>-->
<!-- </div>-->
</div>`
return tipHtml
}
}
},
]
}
let chart:EChartsType
const initChart = () => {
const chart = echarts.init(document.getElementById(props.id))
chart.setOption(options)
return chart
}
onMounted(() => {
chart = initChart()
window.addEventListener('resize', function () {
chart && chart.resize()
return tipHtml
},
},
},
],
}
let chart: EChartsType
const initChart = () => {
const chart = echarts.init(document.getElementById(props.id))
chart.setOption(options)
return chart
}
onMounted(() => {
chart = initChart()
window.addEventListener('resize', function () {
chart && chart.resize()
})
})
})
</script>

View File

@ -1,35 +1,35 @@
<template>
<div :id="id" :class="className" :style="{height:height,width:width}" />
<div :id="id" :class="className" :style="{ height: height, width: width }" />
</template>
<script lang="ts" setup>
import 'echarts-liquidfill/src/liquidFill.js'
import * as echarts from "echarts";
import {EChartsType} from "echarts/core";
import {onMounted} from "vue";
import 'echarts-liquidfill/src/liquidFill.js'
import * as echarts from 'echarts'
import { EChartsType } from 'echarts/core'
import { onMounted } from 'vue'
let props = defineProps({
className: {
type: String,
default: 'chart'
},
config:{
type: Object,
default: ()=>{}
},
id: {
type: String,
default: 'chart'
},
width: {
type: String,
default: '200px'
},
height: {
type: String,
default: '200px'
}
})
const options = {
let props = defineProps({
className: {
type: String,
default: 'chart',
},
config: {
type: Object,
default: () => {},
},
id: {
type: String,
default: 'chart',
},
width: {
type: String,
default: '200px',
},
height: {
type: String,
default: '200px',
},
})
const options = {
legend: {
data: [
'3-11岁任务数',
@ -38,12 +38,12 @@ const options = {
'60岁全程接种量',
'80岁任务数',
'80岁全程接种量',
'完成率'
]
'完成率',
],
},
xAxis: {
type: 'category',
data: ['街道1', '街道2', '街道3', '街道4', '街道5', '街道6', '街道7']
data: ['街道1', '街道2', '街道3', '街道4', '街道5', '街道6', '街道7'],
},
yAxis: [
{ type: 'value' },
@ -54,7 +54,7 @@ const options = {
// max: 100,
nameTextStyle: {
color: '#ccc',
padding: [0, 0, 10, -30]
padding: [0, 0, 10, -30],
},
splitNumber: 5,
splitLine: {
@ -63,16 +63,16 @@ const options = {
type: 'dashed',
width: 1,
// 使
color: ['#566471', '#566471']
}
color: ['#566471', '#566471'],
},
},
axisLabel: {
show: true,
textStyle: {
fontSize: 12
}
}
}
fontSize: 12,
},
},
},
],
// tooltip: {
// trigger: 'axis',
@ -81,56 +81,60 @@ const options = {
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'shadow'
type: 'shadow',
},
textStyle: {
color: '#fff',
align: 'left',
fontSize: 14
fontSize: 14,
},
axisLine: {//x线
axisLine: {
//x线
show: true,
lineStyle: {//x线
color: '#000',//'#ccc' | 'rgb(128, 128, 128)' | 'rgba(128, 128, 128, 0.5)'
}
lineStyle: {
//x线
color: '#000', //'#ccc' | 'rgb(128, 128, 128)' | 'rgba(128, 128, 128, 0.5)'
},
},
backgroundColor: 'rgba(0,0,0,0.8)',
formatter: function (params) {
console.log(params);
let str = params[0].name + '<br />';
console.log(str);
console.log(params)
let str = params[0].name + '<br />'
console.log(str)
params.forEach((item) => {
console.log(item.seriesName);
console.log(item.seriesName)
if (item.value) {
if (item.seriesName.indexOf('岁全程接种量') != -1) {
str += `<span style="display:inline-block;margin-right:5px;border-radius:50%;width:10px;height:10px;left:5px;background-color: ${item.color}
str += `<span style="display:inline-block;margin-right:5px;border-radius:50%;width:10px;height:10px;left:5px;background-color: ${
item.color
}
"></span>
${item.seriesName}
:
${item.value} <br/>
&nbsp; &nbsp; 全程完成率
: ${item.value/100}%
<br/><br/>`;
}else if (item.seriesName.indexOf('岁任务数') != -1) {
: ${item.value / 100}%
<br/><br/>`
} else if (item.seriesName.indexOf('岁任务数') != -1) {
str += `<span style="display:inline-block;margin-right:5px;border-radius:50%;width:10px;height:10px;left:5px;background-color: ${item.color}
"></span>
${item.seriesName}
:
${item.value}
<br/>`;
}else{
<br/>`
} else {
str += `<span style="display:inline-block;margin-right:5px;border-radius:50%;width:10px;height:10px;left:5px;background-color: ${item.color}
"></span>
${item.seriesName}
:
${item.value}%
<br/>`;
<br/>`
}
}
});
return str;
}
})
return str
},
},
series: [
@ -138,77 +142,76 @@ const options = {
name: '3-11岁任务数',
data: [150, 230, 224, 218, 135, 147, 260],
stack: 'BB',
type: 'bar'
type: 'bar',
},
{
name: '3-11岁全程接种量',
data: [150, 230, 224, 218, 135, 147, 260],
stack: 'BB',
type: 'bar'
type: 'bar',
},
{
name: '60岁任务数',
data: [150, 230, 224, 218, 135, 147, 260],
stack: 'AA',
type: 'bar'
type: 'bar',
},
{
name: '60岁全程接种量',
data: [880, 30, 124, 118, 35, 47, 160],
stack: 'AA',
type: 'bar'
type: 'bar',
},
{
name: '80岁任务数',
data: [660, 30, 124, 118, 35, 47, 160],
stack: 'Ad',
type: 'bar'
type: 'bar',
},
{
name: '80岁全程接种量',
data: [880, 30, 124, 118, 35, 47, 160],
stack: 'Ad',
type: 'bar'
type: 'bar',
},
{
name: '完成率',
data: [50, 130, 124, 18, 35, 47, 160],
yAxisIndex:1,
yAxisIndex: 1,
type: 'line',
markLine: {
symbol: 'none',
itemStyle: {
normal: {
lineStyle: {
type: 'dotted'
}
}
type: 'dotted',
},
},
},
data: [{ type: 'average', name: 'Avg' + '%' }]
data: [{ type: 'average', name: 'Avg' + '%' }],
},
// symbol: 'none',
itemStyle: {
normal: {
lineStyle: {
width: 2,
type: 'solid' //'dotted'线 'solid'线
}
}
}
}
]
};
let chart:EChartsType;
const initChart =()=> {
let chart = echarts.init(document.getElementById(props.id))
chart.setOption(options)
return chart
}
onMounted(()=>{
chart = initChart()
window.addEventListener('resize',function (){
chart&&chart.resize()
type: 'solid', //'dotted'线 'solid'线
},
},
},
},
],
}
let chart: EChartsType
const initChart = () => {
let chart = echarts.init(document.getElementById(props.id))
chart.setOption(options)
return chart
}
onMounted(() => {
chart = initChart()
window.addEventListener('resize', function () {
chart && chart.resize()
})
})
})
</script>

File diff suppressed because one or more lines are too long

View File

@ -1,362 +1,364 @@
<template>
<div :id="id" :class="className" :style="{height:height,width:width}" />
<div :id="id" :class="className" :style="{ height: height, width: width }" />
</template>
<script lang="ts" setup>
import * as echarts from "echarts";
import {EChartsType} from "echarts/core";
import {onMounted} from "vue";
import * as echarts from 'echarts'
import { EChartsType } from 'echarts/core'
import { onMounted } from 'vue'
let props = defineProps({
className: {
type: String,
default: 'chart'
},
config:{
type: Object,
default: ()=>{}
},
id: {
type: String,
default: 'chart'
},
width: {
type: String,
default: '200px'
},
height: {
type: String,
default: '200px'
}
})
const options = {
backgroundColor: '#031d33',
legend: {
top: '20',
x: 'center',
textStyle: {
fontSize: 16,
color: 'rgba(101, 213, 255, 1)',
let props = defineProps({
className: {
type: String,
default: 'chart',
},
icon:
'path://M512 881.777778 512 881.777778C716.222629 881.777778 881.777778 716.222629 881.777778 512 881.777778 307.777371 716.222629 142.222222 512 142.222222 307.777373 142.222222 142.222222 307.777371 142.222222 512 142.222222 716.222629 307.777373 881.777778 512 881.777778L512 881.777778ZM512 1024 512 1024C229.230208 1024 0 794.769789 0 512 0 229.230211 229.230208 0 512 0 794.769789 0 1024 229.230211 1024 512 1024 794.769789 794.769789 1024 512 1024L512 1024Z',
itemWidth: 8, //
itemHeight: 8, //
itemGap: 12, //
},
tooltip: {
show: true,
trigger: 'axis', //axis , item
backgroundColor: 'RGBA(0, 49, 85, 1)',
borderColor: 'rgba(0, 151, 251, 1)',
borderWidth: 1,
borderRadius: 0,
textStyle: {
color: '#BCE9FC',
fontSize: 16,
align: 'left',
config: {
type: Object,
default: () => {},
},
},
grid: {
right: '5%',
top: '10%',
left: '5%',
bottom: '5%',
containLabel: true,
},
xAxis: {
name: '部门',
nameTextStyle: {
color: '#65d5ff',
id: {
type: String,
default: 'chart',
},
type: 'category',
boundaryGap: true,
data: ['HWS', 'SE', 'V&V', 'HQ', 'RPA', 'SC', 'RPA', 'PM', 'CCB', 'RSW'],
axisLabel: {
//
interval: 0, // 1
// margin:15,
width: {
type: String,
default: '200px',
},
height: {
type: String,
default: '200px',
},
})
const options = {
backgroundColor: '#031d33',
legend: {
top: '20',
x: 'center',
textStyle: {
color: '#65D5FF',
fontStyle: 'normal',
fontSize: 16,
color: 'rgba(101, 213, 255, 1)',
},
icon: 'path://M512 881.777778 512 881.777778C716.222629 881.777778 881.777778 716.222629 881.777778 512 881.777778 307.777371 716.222629 142.222222 512 142.222222 307.777373 142.222222 142.222222 307.777371 142.222222 512 142.222222 716.222629 307.777373 881.777778 512 881.777778L512 881.777778ZM512 1024 512 1024C229.230208 1024 0 794.769789 0 512 0 229.230211 229.230208 0 512 0 794.769789 0 1024 229.230211 1024 512 1024 794.769789 794.769789 1024 512 1024L512 1024Z',
itemWidth: 8, //
itemHeight: 8, //
itemGap: 12, //
},
axisTick: {
//
show: false,
},
axisLine: {
//线
lineStyle: {
color: 'rgba(77, 128, 254, 0.2)',
},
},
splitLine: {
// grid 线
tooltip: {
show: true,
lineStyle: {
color: 'rgba(77, 128, 254, 0.2)',
},
},
},
dataZoom: [
{
type: 'slider',
show: true,
bottom: '20px',
borderColor: '#07417a',
backgroundColor: 'transparent',
dataBackground: {
lineStyle: {
color: 'transparent',
shadowOffsetY: 0,
},
areaStyle: {
color: 'transparent',
shadowOffsetY: 0,
},
},
// svg
handleIcon:
'M512 512m-208 0a6.5 6.5 0 1 0 416 0 6.5 6.5 0 1 0-416 0Z M512 192C335.264 192 192 335.264 192 512c0 176.736 143.264 320 320 320s320-143.264 320-320C832 335.264 688.736 192 512 192zM512 800c-159.072 0-288-128.928-288-288 0-159.072 128.928-288 288-288s288 128.928 288 288C800 671.072 671.072 800 512 800z',
handleColor: '#aab6c6',
height: 6,
handleSize: 12,
showDataShadow: false,
filterMode: 'filter',
trigger: 'axis', //axis , item
backgroundColor: 'RGBA(0, 49, 85, 1)',
borderColor: 'rgba(0, 151, 251, 1)',
borderWidth: 1,
borderRadius: 0,
textStyle: {
color: '#ccc',
color: '#BCE9FC',
fontSize: 16,
align: 'left',
},
start: 0,
end: 100,
},
],
yAxis: [
{
name: '个',
grid: {
right: '5%',
top: '10%',
left: '5%',
bottom: '5%',
containLabel: true,
},
xAxis: {
name: '部门',
nameTextStyle: {
color: '#65d5ff',
},
type: 'value',
splitNumber: 3,
type: 'category',
boundaryGap: true,
data: ['HWS', 'SE', 'V&V', 'HQ', 'RPA', 'SC', 'RPA', 'PM', 'CCB', 'RSW'],
axisLabel: {
//
interval: 0, // 1
// margin:15,
textStyle: {
color: '#65D5FF',
fontStyle: 'normal',
fontSize: 16,
},
},
axisLine: {
axisTick: {
//
show: false,
},
axisTick: {
show: false,
axisLine: {
//线
lineStyle: {
color: 'rgba(77, 128, 254, 0.2)',
},
},
splitLine: {
// grid 线
show: true,
lineStyle: {
color: 'rgba(77, 128, 254, 0.2)',
},
},
},
{
name: '',
nameTextStyle: {
color: '#65d5ff'
},
min: 0,
splitLine: {
show: true,
lineStyle: {
color: '#233653'
}
},
axisLine: {
show: true,
lineStyle: {
color: '#233653'
}
},
axisLabel: {
dataZoom: [
{
type: 'slider',
show: true,
bottom: '20px',
borderColor: '#07417a',
backgroundColor: 'transparent',
dataBackground: {
lineStyle: {
color: 'transparent',
shadowOffsetY: 0,
},
areaStyle: {
color: 'transparent',
shadowOffsetY: 0,
},
},
// svg
handleIcon:
'M512 512m-208 0a6.5 6.5 0 1 0 416 0 6.5 6.5 0 1 0-416 0Z M512 192C335.264 192 192 335.264 192 512c0 176.736 143.264 320 320 320s320-143.264 320-320C832 335.264 688.736 192 512 192zM512 800c-159.072 0-288-128.928-288-288 0-159.072 128.928-288 288-288s288 128.928 288 288C800 671.072 671.072 800 512 800z',
handleColor: '#aab6c6',
height: 6,
handleSize: 12,
showDataShadow: false,
filterMode: 'filter',
textStyle: {
color: '#78bdf5'
color: '#ccc',
},
formatter: function(value) {
return value * 100 + '%'
}
start: 0,
end: 100,
},
axisTick: {
show: false
}
}
],
series: [
{
name: '变更',
type: 'pictorialBar',
barWidth: '50%',
label: {
normal: {
],
yAxis: [
{
name: '个',
nameTextStyle: {
color: '#65d5ff',
},
type: 'value',
splitNumber: 3,
axisLabel: {
textStyle: {
color: '#65D5FF',
fontStyle: 'normal',
fontSize: 16,
},
},
axisLine: {
show: false,
},
axisTick: {
show: false,
},
splitLine: {
show: true,
lineStyle: {
color: 'rgba(77, 128, 254, 0.2)',
},
},
},
{
name: '',
nameTextStyle: {
color: '#65d5ff',
},
min: 0,
splitLine: {
show: true,
lineStyle: {
color: '#233653',
},
},
axisLine: {
show: true,
lineStyle: {
color: '#233653',
},
},
axisLabel: {
show: true,
textStyle: {
color: '#78bdf5',
},
formatter: function (value) {
return value * 100 + '%'
},
},
axisTick: {
show: false,
},
},
itemStyle: {
normal: {
color: {
type: 'linear',
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [
],
series: [
{
name: '变更',
type: 'pictorialBar',
barWidth: '50%',
label: {
normal: {
show: false,
},
},
itemStyle: {
normal: {
color: {
type: 'linear',
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [
{
offset: 0,
color: 'rgba(255, 64, 0, 0.8)', // 0%
},
{
offset: 1,
color: 'rgba(0, 34, 66, 0.2)', // 100%
},
],
globalCoord: false, // false
}, //
},
},
symbol:
'path://M12.000,-0.000 C12.000,-0.000 16.074,60.121 22.731,60.121 C26.173,60.121 -3.234,60.121 0.511,60.121 C7.072,60.121 12.000,-0.000 12.000,-0.000 Z',
data: [23, 44, 22, 27, 12, 2, 3, 23, 12, 32],
},
{
name: '新增',
type: 'pictorialBar',
barWidth: '50%',
label: {
normal: {
show: false,
},
},
itemStyle: {
normal: {
color: {
type: 'linear',
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [
{
offset: 0,
color: 'rgba(48, 236, 166,0.8)', // 0%
},
{
offset: 1,
color: 'rgba(0, 34, 66, 0.2)', // 100%
},
],
globalCoord: false, // false
}, //
},
},
symbol:
'path://M12.000,-0.000 C12.000,-0.000 16.074,60.121 22.731,60.121 C26.173,60.121 -3.234,60.121 0.511,60.121 C7.072,60.121 12.000,-0.000 12.000,-0.000 Z',
data: [13, 24, 31, 12, 7, 3, 1, 23, 2, 42],
},
{
name: '废弃',
type: 'pictorialBar',
barWidth: '50%',
label: {
normal: {
show: false,
},
},
itemStyle: {
normal: {
color: {
type: 'linear',
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [
{
offset: 0,
color: 'rgba(161, 159, 158, 0.8)', //
},
{
offset: 1,
color: 'rgba(133, 133, 196, 0.2)', // 100%
},
],
globalCoord: false, // false
}, //
},
},
symbol:
'path://M12.000,-0.000 C12.000,-0.000 16.074,60.121 22.731,60.121 C26.173,60.121 -3.234,60.121 0.511,60.121 C7.072,60.121 12.000,-0.000 12.000,-0.000 Z',
data: [4, 3, 12, 4, 15, 2, 3, 12, 34, 23],
},
{
name: '变化占比',
type: 'line',
data: [0.3, 0.5, 0.3, 0.35, 0.15, 0.05, 0.05, 0.3, 0.35, 0.4, 0.5],
smooth: true,
symbol: 'none',
lineStyle: {
normal: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{
offset: 0,
color: 'rgba(255, 64, 0, 0.8)', // 0%
color: 'rgba(255, 227, 168, 0.3)',
},
{
offset: 0.5,
color: 'rgba(255, 227, 168, 1)',
},
{
offset: 1,
color: 'rgba(0, 34, 66, 0.2)', // 100%
color: 'rgba(255, 227, 168, 0.3)',
},
],
globalCoord: false, // false
}, //
]),
shadowColor: 'rgba(255, 120, 0,1)',
shadowBlur: 10,
},
},
yAxisIndex: 1,
},
symbol:
'path://M12.000,-0.000 C12.000,-0.000 16.074,60.121 22.731,60.121 C26.173,60.121 -3.234,60.121 0.511,60.121 C7.072,60.121 12.000,-0.000 12.000,-0.000 Z',
data: [23, 44, 22, 27, 12, 2, 3, 23, 12, 32],
},
{
name: '新增',
type: 'pictorialBar',
barWidth: '50%',
label: {
normal: {
show: false,
{
name: '变化占比',
yAxisIndex: 1,
type: 'effectScatter',
showEffectOn: 'render',
rippleEffect: {
period: 5,
scale: 3,
brushType: 'stroke',
},
},
itemStyle: {
normal: {
color: {
type: 'linear',
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [
{
offset: 0,
color: 'rgba(48, 236, 166,0.8)', // 0%
},
{
offset: 1,
color: 'rgba(0, 34, 66, 0.2)', // 100%
},
],
globalCoord: false, // false
}, //
hoverAnimation: true,
itemStyle: {
normal: {
color: 'rgba(217,247,249,1)',
shadowBlur: 10,
shadowColor: '#333',
},
},
data: [],
},
symbol:
'path://M12.000,-0.000 C12.000,-0.000 16.074,60.121 22.731,60.121 C26.173,60.121 -3.234,60.121 0.511,60.121 C7.072,60.121 12.000,-0.000 12.000,-0.000 Z',
data: [13, 24, 31, 12, 7, 3, 1, 23, 2, 42],
},
{
name: '废弃',
type: 'pictorialBar',
barWidth: '50%',
label: {
normal: {
show: false,
},
},
itemStyle: {
normal: {
color: {
type: 'linear',
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [
{
offset: 0,
color: 'rgba(161, 159, 158, 0.8)', //
},
{
offset: 1,
color: 'rgba(133, 133, 196, 0.2)', // 100%
},
],
globalCoord: false, // false
}, //
},
},
symbol:
'path://M12.000,-0.000 C12.000,-0.000 16.074,60.121 22.731,60.121 C26.173,60.121 -3.234,60.121 0.511,60.121 C7.072,60.121 12.000,-0.000 12.000,-0.000 Z',
data: [4, 3, 12, 4, 15, 2, 3, 12, 34, 23],
},
{
name: '变化占比',
type: 'line',
data: [0.3,0.5,0.3,0.35,0.15,0.05,0.05,0.3,0.35,0.4,0.5],
smooth: true,
symbol: 'none',
lineStyle: {
normal: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
offset: 0,
color: 'rgba(255, 227, 168, 0.3)'
}, {
offset: 0.5,
color: 'rgba(255, 227, 168, 1)'
}, {
offset: 1,
color: 'rgba(255, 227, 168, 0.3)'
}]),
shadowColor: 'rgba(255, 120, 0,1)',
shadowBlur: 10
}
},
yAxisIndex: 1
},
{
name: '变化占比',
yAxisIndex: 1,
type: 'effectScatter',
showEffectOn: 'render',
rippleEffect: {
period: 5,
scale: 3,
brushType: 'stroke'
},
hoverAnimation: true,
itemStyle: {
normal: {
color: 'rgba(217,247,249,1)',
shadowBlur: 10,
shadowColor: '#333'
}
},
data: []
}
],
};
let chart:EChartsType;
const initChart =()=> {
let chart = echarts.init(document.getElementById(props.id))
chart.setOption(options)
return chart
}
onMounted(()=>{
chart = initChart()
window.addEventListener('resize',function (){
chart&&chart.resize()
],
}
let chart: EChartsType
const initChart = () => {
let chart = echarts.init(document.getElementById(props.id))
chart.setOption(options)
return chart
}
onMounted(() => {
chart = initChart()
window.addEventListener('resize', function () {
chart && chart.resize()
})
})
})
</script>

View File

@ -1,106 +1,105 @@
<template>
<div :id="id" :class="className" :style="{height:height,width:width}" />
<div :id="id" :class="className" :style="{ height: height, width: width }" />
</template>
<script lang="ts" setup>
import 'echarts-liquidfill/src/liquidFill.js'
import * as echarts from "echarts";
import {EChartsType} from "echarts/core";
import {onMounted} from "vue";
import 'echarts-liquidfill/src/liquidFill.js'
import * as echarts from 'echarts'
import { EChartsType } from 'echarts/core'
import { onMounted } from 'vue'
let props = defineProps({
className: {
type: String,
default: 'chart'
},
config:{
type: Object,
default: ()=>{}
},
id: {
type: String,
default: 'chart'
},
width: {
type: String,
default: '200px'
},
height: {
type: String,
default: '200px'
}
})
const options = {
grid: {
top: 10,
left: '2%',
right: '2%',
bottom: '2%',
containLabel: true
},
backgroundColor: '#0F224C', //
series: [
{
type: 'liquidFill', //
radius: '80%', //
center: ['50%', '50%'], //
amplitude: 20, //
data: [0.5,.5,.5], // data
color: [
{
type: 'linear',
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [
{
offset: 0,
color: '#446bf5',
},
{
offset: 1,
color: '#2ca3e2',
},
],
globalCoord: false,
},
], //
backgroundStyle: {
borderWidth: 1, //
// borderColor: '#23cc72', //
color: 'RGBA(51, 66, 127, 0.7)', //
},
label: {
//
position: ['50%', '45%'],
formatter: '50%', //,
textStyle: {
fontSize: '52px', //,
color: '#fff',
},
},
outline: {
// show: false
borderDistance: 0,
itemStyle: {
borderWidth: 2,
borderColor: '#112165',
},
},
let props = defineProps({
className: {
type: String,
default: 'chart',
},
config: {
type: Object,
default: () => {},
},
id: {
type: String,
default: 'chart',
},
width: {
type: String,
default: '200px',
},
height: {
type: String,
default: '200px',
},
],
};
let chart:EChartsType;
const initChart =()=> {
let chart = echarts.init(document.getElementById(props.id))
chart.setOption(options)
return chart
}
onMounted(()=>{
chart = initChart()
window.addEventListener('resize',function (){
chart&&chart.resize()
})
})
const options = {
grid: {
top: 10,
left: '2%',
right: '2%',
bottom: '2%',
containLabel: true,
},
backgroundColor: '#0F224C', //
series: [
{
type: 'liquidFill', //
radius: '80%', //
center: ['50%', '50%'], //
amplitude: 20, //
data: [0.5, 0.5, 0.5], // data
color: [
{
type: 'linear',
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [
{
offset: 0,
color: '#446bf5',
},
{
offset: 1,
color: '#2ca3e2',
},
],
globalCoord: false,
},
], //
backgroundStyle: {
borderWidth: 1, //
// borderColor: '#23cc72', //
color: 'RGBA(51, 66, 127, 0.7)', //
},
label: {
//
position: ['50%', '45%'],
formatter: '50%', //,
textStyle: {
fontSize: '52px', //,
color: '#fff',
},
},
outline: {
// show: false
borderDistance: 0,
itemStyle: {
borderWidth: 2,
borderColor: '#112165',
},
},
},
],
}
let chart: EChartsType
const initChart = () => {
let chart = echarts.init(document.getElementById(props.id))
chart.setOption(options)
return chart
}
onMounted(() => {
chart = initChart()
window.addEventListener('resize', function () {
chart && chart.resize()
})
})
</script>

View File

@ -1,271 +1,269 @@
<template>
<div :id="id" :class="className" :style="{height:height,width:width}" />
<div :id="id" :class="className" :style="{ height: height, width: width }" />
</template>
<script lang="ts" setup>
import * as echarts from "echarts";
import {EChartsType} from "echarts/core";
import {onMounted} from "vue";
import * as echarts from 'echarts'
import { EChartsType } from 'echarts/core'
import { onMounted } from 'vue'
let props = defineProps({
className: {
type: String,
default: 'chart'
},
config:{
type: Object,
default: ()=>{}
},
id: {
type: String,
default: 'chart'
},
width: {
type: String,
default: '200px'
},
height: {
type: String,
default: '200px'
}
})
const color = ['#3c90ff', '#fff225', '#24ffdf', '#ff9c3c', '#7536ff']
const indicator = [
{
text: '文明村',
min: 0,
max: 100
},
{
text: '卫生村',
min: 0,
max: 100
},
{
text: '森林村庄',
min: 0,
max: 100
},
{
text: '全面小康',
min: 0,
max: 100
},
{
text: '景区村庄',
min: 0,
max: 100
}
]
const Data = [80,61,70,86,77]
function setData() {
return [
let props = defineProps({
className: {
type: String,
default: 'chart',
},
config: {
type: Object,
default: () => {},
},
id: {
type: String,
default: 'chart',
},
width: {
type: String,
default: '200px',
},
height: {
type: String,
default: '200px',
},
})
const color = ['#3c90ff', '#fff225', '#24ffdf', '#ff9c3c', '#7536ff']
const indicator = [
{
value: Data,
itemStyle: {
normal: {
lineStyle: {
color: '#4BFFFC',
shadowColor: '#4BFFFC',
shadowBlur: 5
},
shadowColor: '#4BFFFC',
shadowBlur: 5
}
},
areaStyle: {
normal: {
//
color: {
type: 'radial',
x: 0.5, //
y: 0.5, //
r: 1,
colorStops: [
{
offset: 1,
color: '#4BFFFC'
},
{
offset: 0,
color: 'rgba(0,0,0,0)'
}
],
globalCoord: false
},
opacity: 0.8 //
}
}
}
text: '文明村',
min: 0,
max: 100,
},
{
text: '卫生村',
min: 0,
max: 100,
},
{
text: '森林村庄',
min: 0,
max: 100,
},
{
text: '全面小康',
min: 0,
max: 100,
},
{
text: '景区村庄',
min: 0,
max: 100,
},
]
}
function setgauge(i) {
return {
type: 'gauge',
detail: false,
splitNumber: 10, //
radius: '80%', //
center: ['50%', '50%'],
startAngle: 90 + 72 * i + 18, //
endAngle: 90 + 72 * (i + 1) - 18, //
axisLine: {
show: false
},
axisTick: {
show: true,
lineStyle: {
color: '#66ccff',
width: 1
const Data = [80, 61, 70, 86, 77]
function setData() {
return [
{
value: Data,
itemStyle: {
normal: {
lineStyle: {
color: '#4BFFFC',
shadowColor: '#4BFFFC',
shadowBlur: 5,
},
shadowColor: '#4BFFFC',
shadowBlur: 5,
},
},
areaStyle: {
normal: {
//
color: {
type: 'radial',
x: 0.5, //
y: 0.5, //
r: 1,
colorStops: [
{
offset: 1,
color: '#4BFFFC',
},
{
offset: 0,
color: 'rgba(0,0,0,0)',
},
],
globalCoord: false,
},
opacity: 0.8, //
},
},
},
]
}
function setgauge(i) {
return {
type: 'gauge',
detail: false,
splitNumber: 10, //
radius: '80%', //
center: ['50%', '50%'],
startAngle: 90 + 72 * i + 18, //
endAngle: 90 + 72 * (i + 1) - 18, //
axisLine: {
show: false,
},
axisTick: {
show: true,
lineStyle: {
color: '#66ccff',
width: 1,
},
length: 6,
splitNumber: 1,
},
splitLine: {
show: false,
},
axisLabel: {
show: false,
},
length: 6,
splitNumber: 1
},
splitLine: {
show: false
},
axisLabel: {
show: false
}
}
}
function setSpot() {
var scatterData = []
Data.map((o, i) => {
scatterData.push({
value: [o, i],
itemStyle: {
normal: {
color: color[i],
borderColor: '#fff',
borderWidth: 1,
shadowColor: color[i],
shadowBlur: 8
}
}
function setSpot() {
var scatterData = []
Data.map((o, i) => {
scatterData.push({
value: [o, i],
itemStyle: {
normal: {
color: color[i],
borderColor: '#fff',
borderWidth: 1,
shadowColor: color[i],
shadowBlur: 8,
},
},
})
})
return scatterData
}
const options = {
backgroundColor: '#0E1327',
polar: {
center: ['50%', '50%'],
radius: '60%',
},
radar: {
shape: 'circle',
center: ['50%', '50%'],
radius: '60%',
indicator: indicator,
axisName: {
color: '#b7e9fd',
fontSize: 13,
padding: -20,
},
nameGap: 45,
splitNumber: 4,
splitArea: {
// grid
show: true,
areaStyle: {
//
color: ['rgba(27, 50, 66, 0.4)'],
},
},
axisLine: {
//线
lineStyle: {
color: '#5aa3d0',
},
},
splitLine: {
lineStyle: {
color: 'rgba(99,192,251,0.2)', // 线
width: 2, // 线线
},
},
},
angleAxis: {
type: 'category',
data: name,
minInterval: 1,
boundaryGap: false,
clockwise: false,
axisTick: {
show: false,
},
axisLabel: {
show: false,
},
axisLine: {
show: false,
},
splitLine: {
show: false,
},
},
radiusAxis: {
min: 0,
max: 100,
interval: 25,
splitLine: {
show: false,
},
axisTick: {
show: false,
},
axisLine: {
//线
lineStyle: {
color: '#5aa3d0',
},
},
axisLabel: {
fontSize: 12,
color: '#5aa3d0',
align: 'left',
margin: -5,
},
},
series: [
setgauge(0),
setgauge(1),
setgauge(2),
setgauge(3),
setgauge(4),
{
type: 'radar',
silent: true,
lineStyle: {
color: '#66ffff',
},
areaStyle: {
color: 'rgba(102, 255, 255, 0.31)',
},
data: setData(),
},
{
type: 'scatter',
coordinateSystem: 'polar',
symbolSize: 20,
data: setSpot(),
},
],
}
let chart: EChartsType
const initChart = () => {
let chart = echarts.init(document.getElementById(props.id))
chart.setOption(options)
return chart
}
onMounted(() => {
chart = initChart()
window.addEventListener('resize', function () {
chart && chart.resize()
})
})
return scatterData
}
const options = {
backgroundColor: '#0E1327',
polar: {
center: ['50%', '50%'],
radius: '60%'
},
radar: {
shape: 'circle',
center: ['50%', '50%'],
radius: '60%',
indicator: indicator,
axisName: {
color: '#b7e9fd',
fontSize: 13,
padding: -20
},
nameGap: 45,
splitNumber: 4,
splitArea: {
// grid
show: true,
areaStyle: {
//
color: ['rgba(27, 50, 66, 0.4)']
}
},
axisLine: {
//线
lineStyle: {
color: '#5aa3d0'
}
},
splitLine: {
lineStyle: {
color: 'rgba(99,192,251,0.2)', // 线
width: 2 // 线线
}
}
},
angleAxis: {
type: 'category',
data: name,
minInterval: 1,
boundaryGap: false,
clockwise: false,
axisTick: {
show: false
},
axisLabel: {
show: false
},
axisLine: {
show: false
},
splitLine: {
show: false
}
},
radiusAxis: {
min: 0,
max: 100,
interval: 25,
splitLine: {
show: false
},
axisTick: {
show: false
},
axisLine: {
//线
lineStyle: {
color: '#5aa3d0'
}
},
axisLabel: {
fontSize: 12,
color: '#5aa3d0',
align: 'left',
margin: -5
}
},
series: [
setgauge(0),
setgauge(1),
setgauge(2),
setgauge(3),
setgauge(4),
{
type: 'radar',
silent: true,
lineStyle: {
color: '#66ffff'
},
areaStyle: {
color: 'rgba(102, 255, 255, 0.31)'
},
data: setData()
},
{
type: 'scatter',
coordinateSystem: 'polar',
symbolSize: 20,
data: setSpot()
}
]
};
let chart:EChartsType;
const initChart =()=> {
let chart = echarts.init(document.getElementById(props.id))
chart.setOption(options)
return chart
}
onMounted(()=>{
chart = initChart()
window.addEventListener('resize',function (){
chart&&chart.resize()
})
})
</script>

View File

@ -1,200 +1,201 @@
<template>
<div :id="id" :class="className" :style="{height:height,width:width}" />
<div :id="id" :class="className" :style="{ height: height, width: width }" />
</template>
<script lang="ts" setup>
import * as echarts from "echarts";
import {EChartsType} from "echarts/core";
import {onMounted} from "vue";
import * as echarts from 'echarts'
import { EChartsType } from 'echarts/core'
import { onMounted } from 'vue'
let props = defineProps({
className: {
type: String,
default: 'chart'
},
config:{
type: Object,
default: ()=>{}
},
id: {
type: String,
default: 'chart'
},
width: {
type: String,
default: '200px'
},
height: {
type: String,
default: '200px'
}
})
let color = ['#0E7CE2', '#FF8352', '#E271DE', '#F8456B', '#00FFFF', '#4AEAB0'];
let echartData = [
{
name: '设备1',
value: '3720',
},
{
name: '设备2',
value: '2920',
},
{
name: '设备3',
value: '2200',
},
{
name: '设备4',
value: '1420',
},
];
let formatNumber = function (num) {
let reg = /(?=(\B)(\d{3})+$)/g;
return num.toString().replace(reg, ',');
};
const options = {
backgroundColor: '#364686',
color: color,
title: [
{
text: '设备数',
x: 'center',
top: '40%',
textStyle: {
color: '#fff',
fontSize: 18,
fontWeight: '100',
},
let props = defineProps({
className: {
type: String,
default: 'chart',
},
{
text: '60%',
x: 'center',
top: '50%',
textStyle: {
fontSize: 30,
color: '#00f0ff',
foontWeight: '500',
},
config: {
type: Object,
default: () => {},
},
],
polar: {
radius: ['44%', '50%'],
center: ['50%', '50%'],
},
angleAxis: {
max: 100,
show: false,
},
radiusAxis: {
type: 'category',
show: true,
axisLabel: {
show: false,
id: {
type: String,
default: 'chart',
},
axisLine: {
show: false,
width: {
type: String,
default: '200px',
},
axisTick: {
show: false,
height: {
type: String,
default: '200px',
},
},
series: [
{
type: 'pie',
radius: ['55%', '67%'],
center: ['50%', '50%'],
data: echartData,
hoverAnimation: false,
itemStyle: {
normal: {
borderColor: '#364684',
borderWidth: 2,
},
},
labelLine: {
normal: {
length: 60,
length2: 60,
lineStyle: {
color: '#e6e6e6',
},
},
},
label: {
normal: {
formatter: (params) => {
return '{icon|●}{name|' + params.name + '}\n{value|' + formatNumber(params.value) + '}';
},
padding: [0, -70, 30, -70],
rich: {
icon: {
fontSize: 14,
align: 'left',
padding: [4, 0, 0, 0],
},
name: {
fontSize: 14,
align: 'left',
padding: [4, 0, 0, 0],
color: '#fff',
},
value: {
fontSize: 18,
fontWeight: 'bold',
color: '#fff',
align: 'left',
},
},
},
},
},
{
name: '',
type: 'pie',
startAngle: 90,
radius: '50%',
hoverAnimation: false,
center: ['50%', '50%'],
itemStyle: {
normal: {
labelLine: {
show: false,
},
color: new echarts.graphic.RadialGradient(0.5, 0.5, 1, [
{
offset: 1,
color: 'rgba(50,171,241, 1)',
},
{
offset: 0,
color: 'rgba(55,70,130, 0)',
},
]),
// borderWidth: 1,
// borderColor: '',
shadowBlur: 10,
// shadowColor: 'rgba(55,70,130, 1)'
},
},
data: [
{
value: 100,
},
],
},
],
};
let chart:EChartsType;
const initChart =()=> {
let chart = echarts.init(document.getElementById(props.id))
chart.setOption(options)
return chart
}
onMounted(()=>{
chart = initChart()
window.addEventListener('resize',function (){
chart&&chart.resize()
})
let color = ['#0E7CE2', '#FF8352', '#E271DE', '#F8456B', '#00FFFF', '#4AEAB0']
let echartData = [
{
name: '设备1',
value: '3720',
},
{
name: '设备2',
value: '2920',
},
{
name: '设备3',
value: '2200',
},
{
name: '设备4',
value: '1420',
},
]
let formatNumber = function (num) {
let reg = /(?=(\B)(\d{3})+$)/g
return num.toString().replace(reg, ',')
}
})
const options = {
backgroundColor: '#364686',
color: color,
title: [
{
text: '设备数',
x: 'center',
top: '40%',
textStyle: {
color: '#fff',
fontSize: 18,
fontWeight: '100',
},
},
{
text: '60%',
x: 'center',
top: '50%',
textStyle: {
fontSize: 30,
color: '#00f0ff',
foontWeight: '500',
},
},
],
polar: {
radius: ['44%', '50%'],
center: ['50%', '50%'],
},
angleAxis: {
max: 100,
show: false,
},
radiusAxis: {
type: 'category',
show: true,
axisLabel: {
show: false,
},
axisLine: {
show: false,
},
axisTick: {
show: false,
},
},
series: [
{
type: 'pie',
radius: ['55%', '67%'],
center: ['50%', '50%'],
data: echartData,
hoverAnimation: false,
itemStyle: {
normal: {
borderColor: '#364684',
borderWidth: 2,
},
},
labelLine: {
normal: {
length: 60,
length2: 60,
lineStyle: {
color: '#e6e6e6',
},
},
},
label: {
normal: {
formatter: (params) => {
return (
'{icon|●}{name|' + params.name + '}\n{value|' + formatNumber(params.value) + '}'
)
},
padding: [0, -70, 30, -70],
rich: {
icon: {
fontSize: 14,
align: 'left',
padding: [4, 0, 0, 0],
},
name: {
fontSize: 14,
align: 'left',
padding: [4, 0, 0, 0],
color: '#fff',
},
value: {
fontSize: 18,
fontWeight: 'bold',
color: '#fff',
align: 'left',
},
},
},
},
},
{
name: '',
type: 'pie',
startAngle: 90,
radius: '50%',
hoverAnimation: false,
center: ['50%', '50%'],
itemStyle: {
normal: {
labelLine: {
show: false,
},
color: new echarts.graphic.RadialGradient(0.5, 0.5, 1, [
{
offset: 1,
color: 'rgba(50,171,241, 1)',
},
{
offset: 0,
color: 'rgba(55,70,130, 0)',
},
]),
// borderWidth: 1,
// borderColor: '',
shadowBlur: 10,
// shadowColor: 'rgba(55,70,130, 1)'
},
},
data: [
{
value: 100,
},
],
},
],
}
let chart: EChartsType
const initChart = () => {
let chart = echarts.init(document.getElementById(props.id))
chart.setOption(options)
return chart
}
onMounted(() => {
chart = initChart()
window.addEventListener('resize', function () {
chart && chart.resize()
})
})
</script>

View File

@ -1,149 +1,147 @@
<template>
<div :id="id" :class="className" :style="{height:height,width:width}" />
<div :id="id" :class="className" :style="{ height: height, width: width }" />
</template>
<script lang="ts" setup>
import * as echarts from "echarts";
import {EChartsType} from "echarts/core";
import {onMounted} from "vue";
import * as echarts from 'echarts'
import { EChartsType } from 'echarts/core'
import { onMounted } from 'vue'
let props = defineProps({
className: {
type: String,
default: 'chart'
},
config:{
type: Object,
default: ()=>{}
},
id: {
type: String,
default: 'chart'
},
width: {
type: String,
default: '200px'
},
height: {
type: String,
default: '200px'
}
})
const options = {
title: [
{
text: '已完成',
x: 'center',
top: '52%',
textStyle: {
color: '#FFFFFF',
fontSize: 16,
fontWeight: '100',
},
let props = defineProps({
className: {
type: String,
default: 'chart',
},
{
text: '75%',
x: 'center',
y: 'center',
textStyle: {
fontSize: '12',
color: '#FFFFFF',
fontFamily: 'DINAlternate-Bold, DINAlternate',
foontWeight: '600',
},
config: {
type: Object,
default: () => {},
},
],
backgroundColor: '#111',
polar: {
radius: ['42%', '52%'],
center: ['50%', '50%'],
},
angleAxis: {
max: 100,
show: false,
},
radiusAxis: {
type: 'category',
show: true,
axisLabel: {
show: false,
id: {
type: String,
default: 'chart',
},
axisLine: {
show: false,
width: {
type: String,
default: '200px',
},
axisTick: {
show: false,
height: {
type: String,
default: '200px',
},
},
series: [
{
name: '',
type: 'bar',
roundCap: true,
barWidth: 30,
showBackground: true,
backgroundStyle: {
color: 'rgba(66, 66, 66, .3)',
},
data: [60],
coordinateSystem: 'polar',
itemStyle: {
normal: {
color: new echarts.graphic.LinearGradient(0, 1, 0, 0, [
{
offset: 0,
color: '#16CEB9',
},
{
offset: 1,
color: '#6648FF',
},
]),
},
},
},
{
name: '',
type: 'pie',
startAngle: 80,
radius: ['56%'],
hoverAnimation: false,
center: ['50%', '50%'],
itemStyle: {
color: 'rgba(66, 66, 66, .1)',
borderWidth: 1,
borderColor: '#5269EE',
},
data: [100],
},
{
name: '',
type: 'pie',
startAngle: 80,
radius: ['38%'],
hoverAnimation: false,
center: ['50%', '50%'],
itemStyle: {
color: 'rgba(66, 66, 66, .1)',
borderWidth: 1,
borderColor: '#5269EE',
},
data: [100],
},
],
};
let chart:EChartsType;
const initChart =()=> {
let chart = echarts.init(document.getElementById(props.id))
chart.setOption(options)
return chart
}
onMounted(()=>{
chart = initChart()
window.addEventListener('resize',function (){
chart&&chart.resize()
})
})
const options = {
title: [
{
text: '已完成',
x: 'center',
top: '52%',
textStyle: {
color: '#FFFFFF',
fontSize: 16,
fontWeight: '100',
},
},
{
text: '75%',
x: 'center',
y: 'center',
textStyle: {
fontSize: '12',
color: '#FFFFFF',
fontFamily: 'DINAlternate-Bold, DINAlternate',
foontWeight: '600',
},
},
],
backgroundColor: '#111',
polar: {
radius: ['42%', '52%'],
center: ['50%', '50%'],
},
angleAxis: {
max: 100,
show: false,
},
radiusAxis: {
type: 'category',
show: true,
axisLabel: {
show: false,
},
axisLine: {
show: false,
},
axisTick: {
show: false,
},
},
series: [
{
name: '',
type: 'bar',
roundCap: true,
barWidth: 30,
showBackground: true,
backgroundStyle: {
color: 'rgba(66, 66, 66, .3)',
},
data: [60],
coordinateSystem: 'polar',
itemStyle: {
normal: {
color: new echarts.graphic.LinearGradient(0, 1, 0, 0, [
{
offset: 0,
color: '#16CEB9',
},
{
offset: 1,
color: '#6648FF',
},
]),
},
},
},
{
name: '',
type: 'pie',
startAngle: 80,
radius: ['56%'],
hoverAnimation: false,
center: ['50%', '50%'],
itemStyle: {
color: 'rgba(66, 66, 66, .1)',
borderWidth: 1,
borderColor: '#5269EE',
},
data: [100],
},
{
name: '',
type: 'pie',
startAngle: 80,
radius: ['38%'],
hoverAnimation: false,
center: ['50%', '50%'],
itemStyle: {
color: 'rgba(66, 66, 66, .1)',
borderWidth: 1,
borderColor: '#5269EE',
},
data: [100],
},
],
}
let chart: EChartsType
const initChart = () => {
let chart = echarts.init(document.getElementById(props.id))
chart.setOption(options)
return chart
}
onMounted(() => {
chart = initChart()
window.addEventListener('resize', function () {
chart && chart.resize()
})
})
</script>

View File

@ -1,85 +1,104 @@
<template>
<div :id="id" :class="className" :style="{height:height,width:width}" />
<div :id="id" :class="className" :style="{ height: height, width: width }" />
</template>
<script lang="ts" setup>
import * as echarts from "echarts";
import {EChartsType} from "echarts/core";
import {onMounted} from "vue";
import * as echarts from 'echarts'
import { EChartsType } from 'echarts/core'
import { onMounted } from 'vue'
let props = defineProps({
className: {
type: String,
default: 'chart'
},
config:{
type: Object,
default: ()=>{}
},
id: {
type: String,
default: 'chart'
},
width: {
type: String,
default: '200px'
},
height: {
type: String,
default: '200px'
}
})
var data = [],data2=[];
var trafficWay = [
{
name: '病假',
value: 20
},{
name: '事假',
value: 1
},{
name: '婚假',
value: 30
},{
name: '丧假',
value: 40
},{
name: '年休假',
value: 40
}];
var color=['#2A8BFD','#BAFF7F','#00FAC1','#00CAFF','#FDE056','#4ED33C','#FF8A26','#FF5252','#9689FF','#CB00FF']
for (var i = 0; i < trafficWay.length; i++) {
data.push({
value: trafficWay[i].value,
name: trafficWay[i].name,
itemStyle: {
normal: {
borderWidth: 8,
shadowBlur: 20,
borderRadius:20,
borderColor:color[i],
shadowColor: color[i]
}
}
}, {
value: 5,
name: '',
itemStyle: {
normal: {
label: {
show: false
let props = defineProps({
className: {
type: String,
default: 'chart',
},
config: {
type: Object,
default: () => {},
},
id: {
type: String,
default: 'chart',
},
width: {
type: String,
default: '200px',
},
height: {
type: String,
default: '200px',
},
})
var data = [],
data2 = []
var trafficWay = [
{
name: '病假',
value: 20,
},
{
name: '事假',
value: 1,
},
{
name: '婚假',
value: 30,
},
{
name: '丧假',
value: 40,
},
{
name: '年休假',
value: 40,
},
]
var color = [
'#2A8BFD',
'#BAFF7F',
'#00FAC1',
'#00CAFF',
'#FDE056',
'#4ED33C',
'#FF8A26',
'#FF5252',
'#9689FF',
'#CB00FF',
]
for (var i = 0; i < trafficWay.length; i++) {
data.push(
{
value: trafficWay[i].value,
name: trafficWay[i].name,
itemStyle: {
normal: {
borderWidth: 8,
shadowBlur: 20,
borderRadius: 20,
borderColor: color[i],
shadowColor: color[i],
},
},
labelLine: {
show: false
},
{
value: 5,
name: '',
itemStyle: {
normal: {
label: {
show: false,
},
labelLine: {
show: false,
},
color: 'rgba(0, 0, 0, 0)',
borderColor: 'rgba(0, 0, 0, 0)',
borderWidth: 0,
},
},
color: 'rgba(0, 0, 0, 0)',
borderColor: 'rgba(0, 0, 0, 0)',
borderWidth: 0
}
}
});
data2.push({
},
)
data2.push(
{
value: trafficWay[i].value,
name: trafficWay[i].name,
},
@ -89,325 +108,330 @@ for (var i = 0; i < trafficWay.length; i++) {
itemStyle: {
normal: {
label: {
show: false
show: false,
},
labelLine: {
show: false
show: false,
},
color: 'rgba(0, 0, 0, 0)',
borderColor: 'rgba(0, 0, 0, 0)',
borderWidth: 0,
opacity:0.2
}
}
}
)
}
let angle = 0;//
const option = {
backgroundColor:"#061740",
color : color,
legend:{
right:'10%',
top:'10%',
icon:'rect',
itemWidth:15,
itemHeight:15,
textStyle:{
color:'#ffffff',
}
},
series: [
{//线1
name: "ring5",
type: 'custom',
coordinateSystem: "none",
renderItem: function(params, api) {
return {
type: 'arc',
shape: {
cx: api.getWidth() / 3,
cy: api.getHeight() / 2,
r: Math.min(api.getWidth(), api.getHeight()) / 2 * 0.6,
startAngle: (0+angle) * Math.PI / 180,
endAngle: (90+angle) * Math.PI / 180
opacity: 0.2,
},
style: {
stroke: '#4EE9E6',
fill: "transparent",
lineWidth: 1.5
},
silent: true
};
},
},
data: [0]
},
{//线1
name: "ring5",
type: 'custom',
coordinateSystem: "none",
renderItem: function(params, api) {
return {
type: 'arc',
shape: {
cx: api.getWidth() / 3,
cy: api.getHeight() / 2,
r: Math.min(api.getWidth(), api.getHeight()) / 2 * 0.6,
startAngle: (180+angle) * Math.PI / 180,
endAngle: (270+angle) * Math.PI / 180
},
style: {
stroke: "#4EE9E6",
fill: "transparent",
lineWidth: 1.5
},
silent: true
};
},
data: [0]
},
{//线2
name: "ring5",
type: 'custom',
coordinateSystem: "none",
renderItem: function(params, api) {
return {
type: 'arc',
shape: {
cx: api.getWidth() / 3,
cy: api.getHeight() / 2,
r: Math.min(api.getWidth(), api.getHeight()) / 2 * 0.65,
startAngle: (270+-angle) * Math.PI / 180,
endAngle: (40+-angle) * Math.PI / 180
},
style: {
stroke: "#4EE9E6",
fill: "transparent",
lineWidth: 1.5
},
silent: true
};
},
data: [0]
},
{//线2
name: "ring5",
type: 'custom',
coordinateSystem: "none",
renderItem: function(params, api) {
return {
type: 'arc',
shape: {
cx: api.getWidth() / 3,
cy: api.getHeight() / 2,
r: Math.min(api.getWidth(), api.getHeight()) / 2 * 0.65,
startAngle: (90+-angle) * Math.PI / 180,
endAngle: (220+-angle) * Math.PI / 180
},
style: {
stroke: "#4EE9E6",
fill: "transparent",
lineWidth: 1.5
},
silent: true
};
},
data: [0]
},
{//绿1
name: "ring5",
type: 'custom',
coordinateSystem: "none",
renderItem: function(params, api) {
let x0 = api.getWidth() / 3;
let y0 = api.getHeight() / 2;
let r = Math.min(api.getWidth(), api.getHeight()) / 2 * 0.65;
let point = getCirlPoint(x0, y0, r, (90+-angle))
return {
type: 'circle',
shape: {
cx: point.x,
cy: point.y,
r: 4
},
style: {
stroke: "#66FFFF",//
fill: "#66FFFF"
},
silent: true
};
},
data: [0]
},
{//绿2
name: "ring5", //绿
type: 'custom',
coordinateSystem: "none",
renderItem: function(params, api) {
let x0 = api.getWidth() / 3;
let y0 = api.getHeight() / 2;
let r = Math.min(api.getWidth(), api.getHeight()) / 2 * 0.65;
let point = getCirlPoint(x0, y0, r, (270+-angle))
return {
type: 'circle',
shape: {
cx: point.x,
cy: point.y,
r: 4
},
style: {
stroke: "#66FFFF",//
fill: "#66FFFF"
},
silent: true
};
},
data: [0]
},
{//绿3
name: "ring5",
type: 'custom',
coordinateSystem: "none",
renderItem: function(params, api) {
let x0 = api.getWidth() / 3;
let y0 = api.getHeight() / 2;
let r = Math.min(api.getWidth(), api.getHeight()) / 2 * 0.6;
let point = getCirlPoint(x0, y0, r, (90+angle))
return {
type: 'circle',
shape: {
cx: point.x,
cy: point.y,
r: 4
},
style: {
stroke: "#66FFFF",//
fill: "#66FFFF"
},
silent: true
};
},
data: [0]
},
{//绿4
name: "ring5", //绿
type: 'custom',
coordinateSystem: "none",
renderItem: function(params, api) {
let x0 = api.getWidth() / 3;
let y0 = api.getHeight() / 2;
let r = Math.min(api.getWidth(), api.getHeight()) / 2 * 0.6;
let point = getCirlPoint(x0, y0, r, (270+angle))
return {
type: 'circle',
shape: {
cx: point.x,
cy: point.y,
r: 4
},
style: {
stroke: "#66FFFF",//
fill: "#66FFFF"
},
silent: true
};
},
data: [0]
},
{
name: '',
type: 'pie',
clockWise: false,
radius: ['98%', '95%'],
hoverAnimation: false,
center:['33.33%','50%'],
top:"center",
itemStyle: {
normal:{
label: {
show:false
}
}
},
data:data
},
{
type: 'pie',
top:"center",
startAngle:90,
clockwise:false,
center:['33.33%','50%'],
legendHoverLink:false,
hoverAnimation: false,
radius: ['94%', '55%'],
itemStyle: {
opacity:0.15
},
label: {
show: false,
position: 'center'
},
labelLine: {
show: false
},
data:data2
},
{
name: '',
type: 'pie',
clockWise: false,
center:['33.33%','50%'],
radius: ['39%', '38%'],
hoverAnimation: false,
top:"center",
itemStyle: {
normal:{
label: {
show:false
}
}
},
data:data
},
]
};
//(x0,y0rangle)
function getCirlPoint(x0, y0, r, angle) {
let x1 = x0 + r * Math.cos(angle * Math.PI / 180)
let y1 = y0 + r * Math.sin(angle * Math.PI / 180)
return {
x: x1,
y: y1
)
}
}
let angle = 0 //
let chart:EChartsType;
const initChart =()=> {
let chart = echarts.init(document.getElementById(props.id))
draw(chart)
return chart
}
function draw(chart){
angle = angle+3
chart.setOption(option, true)
//window.requestAnimationFrame(draw);
}
const option = {
backgroundColor: '#061740',
color: color,
legend: {
right: '10%',
top: '10%',
icon: 'rect',
itemWidth: 15,
itemHeight: 15,
textStyle: {
color: '#ffffff',
},
},
series: [
{
//线1
name: 'ring5',
type: 'custom',
coordinateSystem: 'none',
renderItem: function (params, api) {
return {
type: 'arc',
shape: {
cx: api.getWidth() / 3,
cy: api.getHeight() / 2,
r: (Math.min(api.getWidth(), api.getHeight()) / 2) * 0.6,
startAngle: ((0 + angle) * Math.PI) / 180,
endAngle: ((90 + angle) * Math.PI) / 180,
},
style: {
stroke: '#4EE9E6',
fill: 'transparent',
lineWidth: 1.5,
},
silent: true,
}
},
data: [0],
},
{
//线1
name: 'ring5',
type: 'custom',
coordinateSystem: 'none',
renderItem: function (params, api) {
return {
type: 'arc',
shape: {
cx: api.getWidth() / 3,
cy: api.getHeight() / 2,
r: (Math.min(api.getWidth(), api.getHeight()) / 2) * 0.6,
startAngle: ((180 + angle) * Math.PI) / 180,
endAngle: ((270 + angle) * Math.PI) / 180,
},
style: {
stroke: '#4EE9E6',
fill: 'transparent',
lineWidth: 1.5,
},
silent: true,
}
},
data: [0],
},
{
//线2
name: 'ring5',
type: 'custom',
coordinateSystem: 'none',
renderItem: function (params, api) {
return {
type: 'arc',
shape: {
cx: api.getWidth() / 3,
cy: api.getHeight() / 2,
r: (Math.min(api.getWidth(), api.getHeight()) / 2) * 0.65,
startAngle: ((270 + -angle) * Math.PI) / 180,
endAngle: ((40 + -angle) * Math.PI) / 180,
},
style: {
stroke: '#4EE9E6',
fill: 'transparent',
lineWidth: 1.5,
},
silent: true,
}
},
data: [0],
},
{
//线2
name: 'ring5',
type: 'custom',
coordinateSystem: 'none',
renderItem: function (params, api) {
return {
type: 'arc',
shape: {
cx: api.getWidth() / 3,
cy: api.getHeight() / 2,
r: (Math.min(api.getWidth(), api.getHeight()) / 2) * 0.65,
startAngle: ((90 + -angle) * Math.PI) / 180,
endAngle: ((220 + -angle) * Math.PI) / 180,
},
style: {
stroke: '#4EE9E6',
fill: 'transparent',
lineWidth: 1.5,
},
silent: true,
}
},
data: [0],
},
{
//绿1
name: 'ring5',
type: 'custom',
coordinateSystem: 'none',
renderItem: function (params, api) {
let x0 = api.getWidth() / 3
let y0 = api.getHeight() / 2
let r = (Math.min(api.getWidth(), api.getHeight()) / 2) * 0.65
let point = getCirlPoint(x0, y0, r, 90 + -angle)
return {
type: 'circle',
shape: {
cx: point.x,
cy: point.y,
r: 4,
},
style: {
stroke: '#66FFFF', //
fill: '#66FFFF',
},
silent: true,
}
},
data: [0],
},
{
//绿2
name: 'ring5', //绿
type: 'custom',
coordinateSystem: 'none',
renderItem: function (params, api) {
let x0 = api.getWidth() / 3
let y0 = api.getHeight() / 2
let r = (Math.min(api.getWidth(), api.getHeight()) / 2) * 0.65
let point = getCirlPoint(x0, y0, r, 270 + -angle)
return {
type: 'circle',
shape: {
cx: point.x,
cy: point.y,
r: 4,
},
style: {
stroke: '#66FFFF', //
fill: '#66FFFF',
},
silent: true,
}
},
data: [0],
},
{
//绿3
name: 'ring5',
type: 'custom',
coordinateSystem: 'none',
renderItem: function (params, api) {
let x0 = api.getWidth() / 3
let y0 = api.getHeight() / 2
let r = (Math.min(api.getWidth(), api.getHeight()) / 2) * 0.6
let point = getCirlPoint(x0, y0, r, 90 + angle)
return {
type: 'circle',
shape: {
cx: point.x,
cy: point.y,
r: 4,
},
style: {
stroke: '#66FFFF', //
fill: '#66FFFF',
},
silent: true,
}
},
data: [0],
},
{
//绿4
name: 'ring5', //绿
type: 'custom',
coordinateSystem: 'none',
renderItem: function (params, api) {
let x0 = api.getWidth() / 3
let y0 = api.getHeight() / 2
let r = (Math.min(api.getWidth(), api.getHeight()) / 2) * 0.6
let point = getCirlPoint(x0, y0, r, 270 + angle)
return {
type: 'circle',
shape: {
cx: point.x,
cy: point.y,
r: 4,
},
style: {
stroke: '#66FFFF', //
fill: '#66FFFF',
},
silent: true,
}
},
data: [0],
},
{
name: '',
type: 'pie',
clockWise: false,
radius: ['98%', '95%'],
hoverAnimation: false,
center: ['33.33%', '50%'],
top: 'center',
itemStyle: {
normal: {
label: {
show: false,
},
},
},
data: data,
},
{
type: 'pie',
top: 'center',
startAngle: 90,
clockwise: false,
center: ['33.33%', '50%'],
legendHoverLink: false,
hoverAnimation: false,
radius: ['94%', '55%'],
itemStyle: {
opacity: 0.15,
},
label: {
show: false,
position: 'center',
},
labelLine: {
show: false,
},
data: data2,
},
{
name: '',
type: 'pie',
clockWise: false,
center: ['33.33%', '50%'],
radius: ['39%', '38%'],
hoverAnimation: false,
top: 'center',
itemStyle: {
normal: {
label: {
show: false,
},
},
},
data: data,
},
],
}
//(x0,y0rangle)
function getCirlPoint(x0, y0, r, angle) {
let x1 = x0 + r * Math.cos((angle * Math.PI) / 180)
let y1 = y0 + r * Math.sin((angle * Math.PI) / 180)
return {
x: x1,
y: y1,
}
}
onMounted(()=>{
chart = initChart()
setInterval(function() {
//setInterval
let chart: EChartsType
const initChart = () => {
let chart = echarts.init(document.getElementById(props.id))
draw(chart)
}, 100);
return chart
}
function draw(chart) {
angle = angle + 3
chart.setOption(option, true)
//window.requestAnimationFrame(draw);
}
window.addEventListener('resize',function (){
chart&&chart.resize()
onMounted(() => {
chart = initChart()
setInterval(function () {
//setInterval
draw(chart)
}, 100)
window.addEventListener('resize', function () {
chart && chart.resize()
})
})
})
</script>

View File

@ -1,337 +1,338 @@
<template>
<div :id="id" :class="className" :style="{height:height,width:width}" />
<div :id="id" :class="className" :style="{ height: height, width: width }" />
</template>
<script lang="ts" setup>
import * as echarts from "echarts";
import {EChartsType} from "echarts/core";
import {onMounted} from "vue";
import * as echarts from 'echarts'
import { EChartsType } from 'echarts/core'
import { onMounted } from 'vue'
let props = defineProps({
className: {
type: String,
default: 'chart'
},
config:{
type: Object,
default: ()=>{}
},
id: {
type: String,
default: 'chart'
},
width: {
type: String,
default: '200px'
},
height: {
type: String,
default: '200px'
}
})
let datalist = [
{
name: "公共平台"
},
{
name: "系统0000"
},
{
name: "系统0011"
},
{
name: "系统0022"
},
{
name: "系统0033"
},
{
name: "系统0044"
},
{
name: "系统0055"
},{
name: "系统11"
},
{
name: "系统22"
},
{
name: "系统33"
},
{
name: "系统44"
},
{
name: "系统55"
},
{
name: "系统66"
},
{
name: "系统77"
},
{
name: "系统88"
},
{
name: "系统99"
}
];
let linksData = [
{
source: "公共平台",
target: "系统0000",
value: 1044305
},
{
source: "公共平台",
target: "系统0011",
value: 651527
},
{
source: "公共平台",
target: "系统0022",
value: 651527
},
{
source: "公共平台",
target: "系统0033",
value: 486710
},
{
source: "公共平台",
target: "系统0044",
value: 212670
},
{
source: "公共平台",
target: "系统0055",
value: 210400
},{
source: "系统0011",
target: "系统11",
value: 645246
},
{
source: "系统0022",
target: "系统22",
value: 513275
},
{
source: "系统0011",
target: "系统33",
value: 282986
},
{
source: "系统0011",
target: "系统44",
value: 118655
},
{
source: "系统0022",
target: "系统55",
value: 105989
},
{
source: "系统0022",
target: "系统66",
value: 95100
},
{
source: "系统0033",
target: "系统77",
value: 87796
},
{
source: "系统0044",
target: "系统88",
value: 47658
},
{
source: "系统0055",
target: "系统99",
value: 243660
},
];
let Color = [
"#61FEFF",
"#937FE6",
"#2B56D3",
"#87E7AA",
"#937FE6",
"#FF9B97",
"#8f23f5",
"#0576ea",
"#2cb8cf",
"#8A7EE0",
"#2cb8cf",
"#4e70f0",
"#1fa3de",
"#bbc951",
"#FFC14B",
"#b785a6",
]; let Color1 = [
"#04E0F3",
"#682EFC",
"#35A7FE",
"#0DC09F",
"#682EFC",
"#ED6663",
"#8f23f5",
"#0576ea",
"#2cb8cf",
"#8A7EE0",
"#2cb8cf",
"#4e70f0",
"#1fa3de",
"#bbc951",
"#FFC14B",
"#b785a6",
];
let sourceLabel = [
"right",
"left",
"left",
"left",
"left",
"left",
"left",
"left",
"left",
"left",
"left",
"left",
"left",
"left",
"left",
"left"
];
let itemStyleColor = [];
let labelSource = [];
for (let i = 0; i < datalist.length; i++) {
datalist[i].label = {
normal: {
position: sourceLabel[i]
}
};
labelSource.push(sourceLabel[i]);
}
for (let d = 0; d < datalist.length; d++) {
datalist[d].itemStyle = {
normal: {
// color: Color[d]
color: {
type: "linear",
x: 0,
y: 1,
x2: 0,
y2: 0,
colorStops: [
{
offset: 1,
color: Color[d], // 0%
},
{
offset: 0,
color: Color1[d], // 100%
},
],
global: false, // false
let props = defineProps({
className: {
type: String,
default: 'chart',
},
config: {
type: Object,
default: () => {},
},
id: {
type: String,
default: 'chart',
},
width: {
type: String,
default: '200px',
},
height: {
type: String,
default: '200px',
},
})
let datalist = [
{
name: '公共平台',
},
{
name: '系统0000',
},
{
name: '系统0011',
},
{
name: '系统0022',
},
{
name: '系统0033',
},
{
name: '系统0044',
},
{
name: '系统0055',
},
{
name: '系统11',
},
{
name: '系统22',
},
{
name: '系统33',
},
{
name: '系统44',
},
{
name: '系统55',
},
{
name: '系统66',
},
{
name: '系统77',
},
{
name: '系统88',
},
{
name: '系统99',
},
]
let linksData = [
{
source: '公共平台',
target: '系统0000',
value: 1044305,
},
{
source: '公共平台',
target: '系统0011',
value: 651527,
},
{
source: '公共平台',
target: '系统0022',
value: 651527,
},
{
source: '公共平台',
target: '系统0033',
value: 486710,
},
{
source: '公共平台',
target: '系统0044',
value: 212670,
},
{
source: '公共平台',
target: '系统0055',
value: 210400,
},
{
source: '系统0011',
target: '系统11',
value: 645246,
},
{
source: '系统0022',
target: '系统22',
value: 513275,
},
{
source: '系统0011',
target: '系统33',
value: 282986,
},
{
source: '系统0011',
target: '系统44',
value: 118655,
},
{
source: '系统0022',
target: '系统55',
value: 105989,
},
{
source: '系统0022',
target: '系统66',
value: 95100,
},
{
source: '系统0033',
target: '系统77',
value: 87796,
},
{
source: '系统0044',
target: '系统88',
value: 47658,
},
{
source: '系统0055',
target: '系统99',
value: 243660,
},
]
let Color = [
'#61FEFF',
'#937FE6',
'#2B56D3',
'#87E7AA',
'#937FE6',
'#FF9B97',
'#8f23f5',
'#0576ea',
'#2cb8cf',
'#8A7EE0',
'#2cb8cf',
'#4e70f0',
'#1fa3de',
'#bbc951',
'#FFC14B',
'#b785a6',
]
let Color1 = [
'#04E0F3',
'#682EFC',
'#35A7FE',
'#0DC09F',
'#682EFC',
'#ED6663',
'#8f23f5',
'#0576ea',
'#2cb8cf',
'#8A7EE0',
'#2cb8cf',
'#4e70f0',
'#1fa3de',
'#bbc951',
'#FFC14B',
'#b785a6',
]
let sourceLabel = [
'right',
'left',
'left',
'left',
'left',
'left',
'left',
'left',
'left',
'left',
'left',
'left',
'left',
'left',
'left',
'left',
]
let itemStyleColor = []
let labelSource = []
for (let i = 0; i < datalist.length; i++) {
datalist[i].label = {
normal: {
position: sourceLabel[i],
},
}
};
itemStyleColor.push(datalist[d]);
}
const options = {
backgroundColor: "#031d7a",
tooltip: {
trigger: "item",
triggerOn: "mousemove",
formatter: function(params) {
if (params.name == "公共平台") {
return " 公共平台 "
} else {
let value = params.data.value;
if (!value && value !== 0) return 0;
let str = value.toString();
let reg = str.indexOf(".") > -1 ? /(\d)(?=(\d{3})+\.)/g : /(\d)(?=(?:\d{3})+$)/g;
if (params.data.source == "公共平台") {
return params.data.target + " : " + str.replace(reg, "$1,");
} else {
return params.data.source + " : " + str.replace(reg, "$1,");
}
}
}
},
series: [{
type: "sankey",
layout: "none",
top: "4%",
bottom: "12%",
left: "20",
right: "20",
nodeGap: 15,
nodeWidth: 25,
focusNodeAdjacency: "allEdges",
data: itemStyleColor,
links: linksData,
label: {
labelSource.push(sourceLabel[i])
}
for (let d = 0; d < datalist.length; d++) {
datalist[d].itemStyle = {
normal: {
color: "#fff",
fontSize: 14,
formatter: function(params) {
if (params.data.name == '公共平台') {
let strs = params.data.name.split(''); //
let str = ''
for (let i = 0, s; s = strs[i++];) { //
str += s;
if (!(i % 1)) str += '\n'; //
}
return "{white|" + str + "}"
} else {
return params.data.name
}
// color: Color[d]
color: {
type: 'linear',
x: 0,
y: 1,
x2: 0,
y2: 0,
colorStops: [
{
offset: 1,
color: Color[d], // 0%
},
{
offset: 0,
color: Color1[d], // 100%
},
],
global: false, // false
},
rich: {
white: {
fontSize: 16,
lineHeight: 30,
padding: [0, 0, 0, -26]
},
}
itemStyleColor.push(datalist[d])
}
const options = {
backgroundColor: '#031d7a',
tooltip: {
trigger: 'item',
triggerOn: 'mousemove',
formatter: function (params) {
if (params.name == '公共平台') {
return ' 公共平台 '
} else {
let value = params.data.value
if (!value && value !== 0) return 0
let str = value.toString()
let reg = str.indexOf('.') > -1 ? /(\d)(?=(\d{3})+\.)/g : /(\d)(?=(?:\d{3})+$)/g
if (params.data.source == '公共平台') {
return params.data.target + ' : ' + str.replace(reg, '$1,')
} else {
return params.data.source + ' : ' + str.replace(reg, '$1,')
}
}
}
},
},
lineStyle: {
normal: {
opacity: 0.4,
color: "source",
curveness: 0.5
}
},
itemStyle: {
normal: {
borderWidth: 1,
borderColor: "transparent"
}
}
}]
};
let chart:EChartsType;
const initChart =()=> {
let chart = echarts.init(document.getElementById(props.id))
chart.setOption(options)
return chart
}
onMounted(()=>{
chart = initChart()
window.addEventListener('resize',function (){
chart&&chart.resize()
series: [
{
type: 'sankey',
layout: 'none',
top: '4%',
bottom: '12%',
left: '20',
right: '20',
nodeGap: 15,
nodeWidth: 25,
focusNodeAdjacency: 'allEdges',
data: itemStyleColor,
links: linksData,
label: {
normal: {
color: '#fff',
fontSize: 14,
formatter: function (params) {
if (params.data.name == '公共平台') {
let strs = params.data.name.split('') //
let str = ''
for (let i = 0, s; (s = strs[i++]); ) {
//
str += s
if (!(i % 1)) str += '\n' //
}
return '{white|' + str + '}'
} else {
return params.data.name
}
},
rich: {
white: {
fontSize: 16,
lineHeight: 30,
padding: [0, 0, 0, -26],
},
},
},
},
lineStyle: {
normal: {
opacity: 0.4,
color: 'source',
curveness: 0.5,
},
},
itemStyle: {
normal: {
borderWidth: 1,
borderColor: 'transparent',
},
},
},
],
}
let chart: EChartsType
const initChart = () => {
let chart = echarts.init(document.getElementById(props.id))
chart.setOption(options)
return chart
}
onMounted(() => {
chart = initChart()
window.addEventListener('resize', function () {
chart && chart.resize()
})
})
})
</script>

View File

@ -1,66 +1,65 @@
<template>
<div :id="id" :class="className" :style="{height:height,width:width}" />
<div :id="id" :class="className" :style="{ height: height, width: width }" />
</template>
<script lang="ts" setup>
import * as echarts from "echarts";
import {EChartsType} from "echarts/core";
import {onMounted} from "vue";
import * as echarts from 'echarts'
import { EChartsType } from 'echarts/core'
import { onMounted } from 'vue'
let props = defineProps({
className: {
type: String,
default: 'chart'
},
config:{
type: Object,
default: ()=>{}
},
id: {
type: String,
default: 'chart'
},
width: {
type: String,
default: '200px'
},
height: {
type: String,
default: '200px'
}
})
const options = {
grid: {
top: 10,
left: '2%',
right: '2%',
bottom: '2%',
containLabel: true
},
xAxis: {
type: 'category',
data: ['星期一', '星期二', '星期三', '星期四', '星期五', '星期六', '星期日']
},
yAxis: {
type: 'value'
},
series: [
{
data: [150, 230, 150, 80, 70, 110, 130],
type: 'bar'
}
]
};
let chart:EChartsType;
const initChart =()=> {
let chart = echarts.init(document.getElementById(props.id))
chart.setOption(options)
return chart
}
onMounted(()=>{
chart = initChart()
window.addEventListener('resize',function (){
chart&&chart.resize()
let props = defineProps({
className: {
type: String,
default: 'chart',
},
config: {
type: Object,
default: () => {},
},
id: {
type: String,
default: 'chart',
},
width: {
type: String,
default: '200px',
},
height: {
type: String,
default: '200px',
},
})
const options = {
grid: {
top: 10,
left: '2%',
right: '2%',
bottom: '2%',
containLabel: true,
},
xAxis: {
type: 'category',
data: ['星期一', '星期二', '星期三', '星期四', '星期五', '星期六', '星期日'],
},
yAxis: {
type: 'value',
},
series: [
{
data: [150, 230, 150, 80, 70, 110, 130],
type: 'bar',
},
],
}
let chart: EChartsType
const initChart = () => {
let chart = echarts.init(document.getElementById(props.id))
chart.setOption(options)
return chart
}
onMounted(() => {
chart = initChart()
window.addEventListener('resize', function () {
chart && chart.resize()
})
})
})
</script>

View File

@ -1,68 +1,67 @@
<template>
<div :id="id" :class="className" :style="{height:height,width:width}" />
<div :id="id" :class="className" :style="{ height: height, width: width }" />
</template>
<script lang="ts" setup>
import * as echarts from "echarts";
import {EChartsType} from "echarts/core";
import {onMounted} from "vue";
import * as echarts from 'echarts'
import { EChartsType } from 'echarts/core'
import { onMounted } from 'vue'
let props = defineProps({
className: {
type: String,
default: 'chart'
},
config:{
type: Object,
default: ()=>{}
},
id: {
type: String,
default: 'chart'
},
width: {
type: String,
default: '200px'
},
height: {
type: String,
default: '200px'
}
})
const options = {
grid: {
top: 10,
left: '2%',
right: '2%',
bottom: '2%',
containLabel: true
},
xAxis: {
data: ['2017-10-24', '2017-10-25', '2017-10-26', '2017-10-27']
},
yAxis: {},
series: [
{
type: 'candlestick',
data: [
[20, 34, 10, 38],
[40, 35, 30, 50],
[31, 38, 33, 44],
[38, 15, 5, 42]
]
}
]
};
let chart:EChartsType;
const initChart =()=> {
let chart = echarts.init(document.getElementById(props.id))
chart.setOption(options)
return chart
}
onMounted(()=>{
chart = initChart()
window.addEventListener('resize',function (){
chart&&chart.resize()
let props = defineProps({
className: {
type: String,
default: 'chart',
},
config: {
type: Object,
default: () => {},
},
id: {
type: String,
default: 'chart',
},
width: {
type: String,
default: '200px',
},
height: {
type: String,
default: '200px',
},
})
const options = {
grid: {
top: 10,
left: '2%',
right: '2%',
bottom: '2%',
containLabel: true,
},
xAxis: {
data: ['2017-10-24', '2017-10-25', '2017-10-26', '2017-10-27'],
},
yAxis: {},
series: [
{
type: 'candlestick',
data: [
[20, 34, 10, 38],
[40, 35, 30, 50],
[31, 38, 33, 44],
[38, 15, 5, 42],
],
},
],
}
let chart: EChartsType
const initChart = () => {
let chart = echarts.init(document.getElementById(props.id))
chart.setOption(options)
return chart
}
onMounted(() => {
chart = initChart()
window.addEventListener('resize', function () {
chart && chart.resize()
})
})
})
</script>

View File

@ -1,111 +1,110 @@
<template>
<div :id="id" :class="className" :style="{height:height,width:width}" />
<div :id="id" :class="className" :style="{ height: height, width: width }" />
</template>
<script lang="ts" setup>
import * as echarts from "echarts";
import {EChartsType} from "echarts/core";
import {onMounted} from "vue";
import * as echarts from 'echarts'
import { EChartsType } from 'echarts/core'
import { onMounted } from 'vue'
let props = defineProps({
className: {
type: String,
default: 'chart'
},
config:{
type: Object,
default: ()=>{}
},
id: {
type: String,
default: 'chart'
},
width: {
type: String,
default: '200px'
},
height: {
type: String,
default: '200px'
}
})
const options = {
grid: {
top: 0,
left: '2%',
right: '2%',
bottom: '0%',
containLabel: true
},
tooltip: {
trigger: 'item',
formatter: '{a} <br/>{b} : {c}%'
},
toolbox: {
feature: {
dataView: { readOnly: false },
restore: {},
saveAsImage: {}
}
},
legend: {
show:false,
data: ['Show', 'Click', 'Visit', 'Inquiry', 'Order']
},
series: [
{
name: 'Funnel',
type: 'funnel',
left: '10%',
top: 30,
bottom: 10,
width: '80%',
min: 0,
max: 100,
minSize: '0%',
maxSize: '100%',
sort: 'descending',
gap: 2,
label: {
show: true,
position: 'inside'
},
labelLine: {
length: 10,
lineStyle: {
width: 1,
type: 'solid'
}
},
itemStyle: {
borderColor: '#fff',
borderWidth: 1
},
emphasis: {
label: {
fontSize: 20
}
},
data: [
{ value: 60, name: 'Visit' },
{ value: 40, name: 'Inquiry' },
{ value: 20, name: 'Order' },
{ value: 80, name: 'Click' },
{ value: 100, name: 'Show' }
]
}
]
};
let chart:EChartsType;
const initChart =()=> {
let chart = echarts.init(document.getElementById(props.id))
chart.setOption(options)
return chart
}
onMounted(()=>{
chart = initChart()
window.addEventListener('resize',function (){
chart&&chart.resize()
let props = defineProps({
className: {
type: String,
default: 'chart',
},
config: {
type: Object,
default: () => {},
},
id: {
type: String,
default: 'chart',
},
width: {
type: String,
default: '200px',
},
height: {
type: String,
default: '200px',
},
})
const options = {
grid: {
top: 0,
left: '2%',
right: '2%',
bottom: '0%',
containLabel: true,
},
tooltip: {
trigger: 'item',
formatter: '{a} <br/>{b} : {c}%',
},
toolbox: {
feature: {
dataView: { readOnly: false },
restore: {},
saveAsImage: {},
},
},
legend: {
show: false,
data: ['Show', 'Click', 'Visit', 'Inquiry', 'Order'],
},
series: [
{
name: 'Funnel',
type: 'funnel',
left: '10%',
top: 30,
bottom: 10,
width: '80%',
min: 0,
max: 100,
minSize: '0%',
maxSize: '100%',
sort: 'descending',
gap: 2,
label: {
show: true,
position: 'inside',
},
labelLine: {
length: 10,
lineStyle: {
width: 1,
type: 'solid',
},
},
itemStyle: {
borderColor: '#fff',
borderWidth: 1,
},
emphasis: {
label: {
fontSize: 20,
},
},
data: [
{ value: 60, name: 'Visit' },
{ value: 40, name: 'Inquiry' },
{ value: 20, name: 'Order' },
{ value: 80, name: 'Click' },
{ value: 100, name: 'Show' },
],
},
],
}
let chart: EChartsType
const initChart = () => {
let chart = echarts.init(document.getElementById(props.id))
chart.setOption(options)
return chart
}
onMounted(() => {
chart = initChart()
window.addEventListener('resize', function () {
chart && chart.resize()
})
})
})
</script>

View File

@ -1,65 +1,63 @@
<template>
<div :id="id" :class="className" :style="{height:height,width:width}" />
<div :id="id" :class="className" :style="{ height: height, width: width }" />
</template>
<script lang="ts" setup>
import * as echarts from "echarts";
import {EChartsType} from "echarts/core";
import {onMounted} from "vue";
import * as echarts from 'echarts'
import { EChartsType } from 'echarts/core'
import { onMounted } from 'vue'
let props = defineProps({
className: {
type: String,
default: 'chart'
},
config:{
type: Object,
default: ()=>{}
},
id: {
type: String,
default: 'chart'
},
width: {
type: String,
default: '200px'
},
height: {
type: String,
default: '200px'
}
})
const options = {
tooltip: {
formatter: '{a} <br/>{b} : {c}%'
},
series: [
{
name: 'Pressure',
type: 'gauge',
detail: {
formatter: '{value}'
},
data: [
{
value: 50,
name: 'SCORE'
}
]
}
]
};
let chart:EChartsType;
const initChart =()=> {
let chart = echarts.init(document.getElementById(props.id))
chart.setOption(options)
return chart
}
onMounted(()=>{
chart = initChart()
window.addEventListener('resize',function (){
chart&&chart.resize()
let props = defineProps({
className: {
type: String,
default: 'chart',
},
config: {
type: Object,
default: () => {},
},
id: {
type: String,
default: 'chart',
},
width: {
type: String,
default: '200px',
},
height: {
type: String,
default: '200px',
},
})
const options = {
tooltip: {
formatter: '{a} <br/>{b} : {c}%',
},
series: [
{
name: 'Pressure',
type: 'gauge',
detail: {
formatter: '{value}',
},
data: [
{
value: 50,
name: 'SCORE',
},
],
},
],
}
let chart: EChartsType
const initChart = () => {
let chart = echarts.init(document.getElementById(props.id))
chart.setOption(options)
return chart
}
onMounted(() => {
chart = initChart()
window.addEventListener('resize', function () {
chart && chart.resize()
})
})
})
</script>

View File

@ -1,91 +1,90 @@
<template>
<div :id="id" :class="className" :style="{height:height,width:width}" />
<div :id="id" :class="className" :style="{ height: height, width: width }" />
</template>
<script lang="ts" setup>
import * as echarts from "echarts";
import {EChartsType} from "echarts/core";
import {onMounted} from "vue";
import * as echarts from 'echarts'
import { EChartsType } from 'echarts/core'
import { onMounted } from 'vue'
let props = defineProps({
className: {
type: String,
default: 'chart'
},
config:{
type: Object,
default: ()=>{}
},
id: {
type: String,
default: 'chart'
},
width: {
type: String,
default: '200px'
},
height: {
type: String,
default: '200px'
}
})
const axisData = ['Mon', 'Tue', 'Wed', 'Very Loooong Thu', 'Fri', 'Sat', 'Sun'];
const data = axisData.map(function (item, i) {
return Math.round(Math.random() * 1000 * (i + 1));
});
const links = data.map(function (item, i) {
return {
source: i,
target: i + 1
};
});
links.pop();
const options = {
grid: {
top: 10,
left: '2%',
right: '2%',
bottom: '2%',
containLabel: true
},
tooltip: {},
xAxis: {
type: 'category',
boundaryGap: false,
data: axisData
},
yAxis: {
type: 'value'
},
series: [
{
type: 'graph',
layout: 'none',
coordinateSystem: 'cartesian2d',
symbolSize: 40,
label: {
show: true
},
edgeSymbol: ['circle', 'arrow'],
edgeSymbolSize: [4, 10],
data: data,
links: links,
lineStyle: {
color: '#2f4554'
}
}
]
};
let chart:EChartsType;
const initChart =()=> {
let chart = echarts.init(document.getElementById(props.id))
chart.setOption(options)
return chart
}
onMounted(()=>{
chart = initChart()
window.addEventListener('resize',function (){
chart&&chart.resize()
let props = defineProps({
className: {
type: String,
default: 'chart',
},
config: {
type: Object,
default: () => {},
},
id: {
type: String,
default: 'chart',
},
width: {
type: String,
default: '200px',
},
height: {
type: String,
default: '200px',
},
})
const axisData = ['Mon', 'Tue', 'Wed', 'Very Loooong Thu', 'Fri', 'Sat', 'Sun']
const data = axisData.map(function (item, i) {
return Math.round(Math.random() * 1000 * (i + 1))
})
const links = data.map(function (item, i) {
return {
source: i,
target: i + 1,
}
})
links.pop()
const options = {
grid: {
top: 10,
left: '2%',
right: '2%',
bottom: '2%',
containLabel: true,
},
tooltip: {},
xAxis: {
type: 'category',
boundaryGap: false,
data: axisData,
},
yAxis: {
type: 'value',
},
series: [
{
type: 'graph',
layout: 'none',
coordinateSystem: 'cartesian2d',
symbolSize: 40,
label: {
show: true,
},
edgeSymbol: ['circle', 'arrow'],
edgeSymbolSize: [4, 10],
data: data,
links: links,
lineStyle: {
color: '#2f4554',
},
},
],
}
let chart: EChartsType
const initChart = () => {
let chart = echarts.init(document.getElementById(props.id))
chart.setOption(options)
return chart
}
onMounted(() => {
chart = initChart()
window.addEventListener('resize', function () {
chart && chart.resize()
})
})
})
</script>

View File

@ -1,79 +1,77 @@
<template>
<div :id="id" :class="className" :style="{height:height,width:width}" ref="chartsRef"/>
<div :id="id" :class="className" :style="{ height: height, width: width }" ref="chartsRef" />
</template>
<script lang="ts" setup>
import * as echarts from 'echarts'
import { EChartsType } from 'echarts/core'
import { onMounted, ref } from 'vue'
const chartsRef = ref<HTMLElement|null>()
import * as echarts from 'echarts'
import { EChartsType } from 'echarts/core'
import { onMounted, ref } from 'vue'
const chartsRef = ref<HTMLElement | null>()
const props = defineProps({
className: {
type: String,
default: 'chart'
},
xAxisData: {
type: Array,
default: () => ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
},
config: {
type: Object,
default: () => {}
},
seriesData: {
type: Array,
default: () => [150, 230, 224, 218, 135, 147, 260]
},
id: {
type: String,
default: 'chart'
},
width: {
type: String,
default: '200px'
},
height: {
type: String,
default: '200px'
}
})
const options = {
grid: {
top: 10,
left: '2%',
right: '2%',
bottom: '2%',
containLabel: true,
},
xAxis: {
type: 'category',
data: props.xAxisData
},
yAxis: {
type: 'value'
},
series: [
{
data: props.seriesData,
type: 'line'
}
],
...props.config
}
let chart:EChartsType
const initChart = () => {
const chart = echarts.init(chartsRef.value)
chart.setOption(options)
return chart
}
onMounted(() => {
chart = initChart()
window.addEventListener('resize', function () {
chart && chart.resize()
const props = defineProps({
className: {
type: String,
default: 'chart',
},
xAxisData: {
type: Array,
default: () => ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
},
config: {
type: Object,
default: () => {},
},
seriesData: {
type: Array,
default: () => [150, 230, 224, 218, 135, 147, 260],
},
id: {
type: String,
default: 'chart',
},
width: {
type: String,
default: '200px',
},
height: {
type: String,
default: '200px',
},
})
const options = {
grid: {
top: 10,
left: '2%',
right: '2%',
bottom: '2%',
containLabel: true,
},
xAxis: {
type: 'category',
data: props.xAxisData,
},
yAxis: {
type: 'value',
},
series: [
{
data: props.seriesData,
type: 'line',
},
],
...props.config,
}
let chart: EChartsType
const initChart = () => {
const chart = echarts.init(chartsRef.value)
chart.setOption(options)
return chart
}
onMounted(() => {
chart = initChart()
window.addEventListener('resize', function () {
chart && chart.resize()
})
})
})
</script>
<style>
</style>
<style></style>

View File

@ -1,148 +1,145 @@
<template>
<div :id="id" :class="className" :style="{height:height,width:width}" />
<div :id="id" :class="className" :style="{ height: height, width: width }" />
</template>
<script lang="ts" setup>
import * as echarts from "echarts";
import {EChartsType} from "echarts/core";
import {onMounted} from "vue";
let category = [];
let dottedBase = +new Date();
let lineData = [];
let barData = [];
import * as echarts from 'echarts'
import { EChartsType } from 'echarts/core'
import { onMounted } from 'vue'
let category = []
let dottedBase = +new Date()
let lineData = []
let barData = []
for (let i = 0; i < 20; i++) {
let date = new Date((dottedBase += 3600 * 24 * 1000));
category.push(
[date.getFullYear(), date.getMonth() + 1, date.getDate()].join('-')
);
let b = Math.random() * 200;
let d = Math.random() * 200;
barData.push(b);
lineData.push(d + b);
}
let props = defineProps({
className: {
type: String,
default: 'chart'
},
config:{
type: Object,
default: ()=>{}
},
id: {
type: String,
default: 'chart'
},
width: {
type: String,
default: '200px'
},
height: {
type: String,
default: '200px'
for (let i = 0; i < 20; i++) {
let date = new Date((dottedBase += 3600 * 24 * 1000))
category.push([date.getFullYear(), date.getMonth() + 1, date.getDate()].join('-'))
let b = Math.random() * 200
let d = Math.random() * 200
barData.push(b)
lineData.push(d + b)
}
})
const options = {
grid: {
top: 10,
left: '2%',
right: '2%',
bottom: '2%',
containLabel: true
},
backgroundColor: '#0f375f',
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'shadow'
}
},
legend: {
data: ['line', 'bar'],
textStyle: {
color: '#ccc'
}
},
xAxis: {
data: category,
axisLine: {
lineStyle: {
color: '#ccc'
}
}
},
yAxis: {
splitLine: { show: false },
axisLine: {
lineStyle: {
color: '#ccc'
}
}
},
series: [
{
name: 'line',
type: 'line',
smooth: true,
showAllSymbol: true,
symbol: 'emptyCircle',
symbolSize: 15,
data: lineData
let props = defineProps({
className: {
type: String,
default: 'chart',
},
{
name: 'bar',
type: 'bar',
barWidth: 10,
itemStyle: {
borderRadius: 5,
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: '#14c8d4' },
{ offset: 1, color: '#43eec6' }
])
},
data: barData
config: {
type: Object,
default: () => {},
},
{
name: 'line',
type: 'bar',
barGap: '-100%',
barWidth: 10,
itemStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: 'rgba(20,200,212,0.5)' },
{ offset: 0.2, color: 'rgba(20,200,212,0.2)' },
{ offset: 1, color: 'rgba(20,200,212,0)' }
])
},
z: -12,
data: lineData
id: {
type: String,
default: 'chart',
},
width: {
type: String,
default: '200px',
},
height: {
type: String,
default: '200px',
},
{
name: 'dotted',
type: 'pictorialBar',
symbol: 'rect',
itemStyle: {
color: '#0f375f'
},
symbolRepeat: true,
symbolSize: [12, 4],
symbolMargin: 1,
z: -10,
data: lineData
}
]
};
let chart:EChartsType;
const initChart =()=> {
let chart = echarts.init(document.getElementById(props.id))
chart.setOption(options)
return chart
}
onMounted(()=>{
chart = initChart()
window.addEventListener('resize',function (){
chart&&chart.resize()
})
})
const options = {
grid: {
top: 10,
left: '2%',
right: '2%',
bottom: '2%',
containLabel: true,
},
backgroundColor: '#0f375f',
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'shadow',
},
},
legend: {
data: ['line', 'bar'],
textStyle: {
color: '#ccc',
},
},
xAxis: {
data: category,
axisLine: {
lineStyle: {
color: '#ccc',
},
},
},
yAxis: {
splitLine: { show: false },
axisLine: {
lineStyle: {
color: '#ccc',
},
},
},
series: [
{
name: 'line',
type: 'line',
smooth: true,
showAllSymbol: true,
symbol: 'emptyCircle',
symbolSize: 15,
data: lineData,
},
{
name: 'bar',
type: 'bar',
barWidth: 10,
itemStyle: {
borderRadius: 5,
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: '#14c8d4' },
{ offset: 1, color: '#43eec6' },
]),
},
data: barData,
},
{
name: 'line',
type: 'bar',
barGap: '-100%',
barWidth: 10,
itemStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: 'rgba(20,200,212,0.5)' },
{ offset: 0.2, color: 'rgba(20,200,212,0.2)' },
{ offset: 1, color: 'rgba(20,200,212,0)' },
]),
},
z: -12,
data: lineData,
},
{
name: 'dotted',
type: 'pictorialBar',
symbol: 'rect',
itemStyle: {
color: '#0f375f',
},
symbolRepeat: true,
symbolSize: [12, 4],
symbolMargin: 1,
z: -10,
data: lineData,
},
],
}
let chart: EChartsType
const initChart = () => {
let chart = echarts.init(document.getElementById(props.id))
chart.setOption(options)
return chart
}
onMounted(() => {
chart = initChart()
window.addEventListener('resize', function () {
chart && chart.resize()
})
})
</script>

View File

@ -1,89 +1,88 @@
<template>
<div :id="id" :class="className" :style="{height:height,width:width}" />
<div :id="id" :class="className" :style="{ height: height, width: width }" />
</template>
<script lang="ts" setup>
import * as echarts from "echarts";
import {EChartsType} from "echarts/core";
import {onMounted} from "vue";
import * as echarts from 'echarts'
import { EChartsType } from 'echarts/core'
import { onMounted } from 'vue'
let props = defineProps({
className: {
type: String,
default: 'chart'
},
config:{
type: Object,
default: ()=>{}
},
id: {
type: String,
default: 'chart'
},
width: {
type: String,
default: '200px'
},
height: {
type: String,
default: '200px'
}
})
const options = {
grid: {
top: 10,
left: '2%',
right: '2%',
bottom: '2%',
containLabel: true
},
tooltip: {
trigger: 'item'
},
legend: {
top: '0%',
left: 'center'
},
series: [
{
name: 'Access From',
type: 'pie',
radius: ['40%', '70%'],
avoidLabelOverlap: false,
label: {
show: false,
position: 'center'
},
emphasis: {
label: {
show: true,
fontSize: '40',
fontWeight: 'bold'
}
},
labelLine: {
show: false
},
data: [
{ value: 1048, name: 'Search Engine' },
{ value: 735, name: 'Direct' },
{ value: 580, name: 'Email' },
{ value: 484, name: 'Union Ads' },
{ value: 300, name: 'Video Ads' }
]
}
]
};
let chart:EChartsType;
const initChart =()=> {
let chart = echarts.init(document.getElementById(props.id))
chart.setOption(options)
return chart
}
onMounted(()=>{
chart = initChart()
window.addEventListener('resize',function (){
chart&&chart.resize()
let props = defineProps({
className: {
type: String,
default: 'chart',
},
config: {
type: Object,
default: () => {},
},
id: {
type: String,
default: 'chart',
},
width: {
type: String,
default: '200px',
},
height: {
type: String,
default: '200px',
},
})
const options = {
grid: {
top: 10,
left: '2%',
right: '2%',
bottom: '2%',
containLabel: true,
},
tooltip: {
trigger: 'item',
},
legend: {
top: '0%',
left: 'center',
},
series: [
{
name: 'Access From',
type: 'pie',
radius: ['40%', '70%'],
avoidLabelOverlap: false,
label: {
show: false,
position: 'center',
},
emphasis: {
label: {
show: true,
fontSize: '40',
fontWeight: 'bold',
},
},
labelLine: {
show: false,
},
data: [
{ value: 1048, name: 'Search Engine' },
{ value: 735, name: 'Direct' },
{ value: 580, name: 'Email' },
{ value: 484, name: 'Union Ads' },
{ value: 300, name: 'Video Ads' },
],
},
],
}
let chart: EChartsType
const initChart = () => {
let chart = echarts.init(document.getElementById(props.id))
chart.setOption(options)
return chart
}
onMounted(() => {
chart = initChart()
window.addEventListener('resize', function () {
chart && chart.resize()
})
})
})
</script>

View File

@ -1,248 +1,247 @@
<template>
<div :id="id" :class="className" :style="{height:height,width:width}" />
<div :id="id" :class="className" :style="{ height: height, width: width }" />
</template>
<script lang="ts" setup>
import * as echarts from "echarts";
import {EChartsType} from "echarts/core";
import {onMounted} from "vue";
import * as echarts from 'echarts'
import { EChartsType } from 'echarts/core'
import { onMounted } from 'vue'
let props = defineProps({
className: {
type: String,
default: 'chart'
},
config:{
type: Object,
default: ()=>{}
},
id: {
type: String,
default: 'chart'
},
width: {
type: String,
default: '200px'
},
height: {
type: String,
default: '200px'
}
})
const dataBJ = [
[55, 9, 56, 0.46, 18, 6, 1],
[25, 11, 21, 0.65, 34, 9, 2],
[56, 7, 63, 0.3, 14, 5, 3],
[33, 7, 29, 0.33, 16, 6, 4],
[42, 24, 44, 0.76, 40, 16, 5],
[82, 58, 90, 1.77, 68, 33, 6],
[74, 49, 77, 1.46, 48, 27, 7],
[78, 55, 80, 1.29, 59, 29, 8],
[267, 216, 280, 4.8, 108, 64, 9],
[185, 127, 216, 2.52, 61, 27, 10],
[39, 19, 38, 0.57, 31, 15, 11],
[41, 11, 40, 0.43, 21, 7, 12],
[64, 38, 74, 1.04, 46, 22, 13],
[108, 79, 120, 1.7, 75, 41, 14],
[108, 63, 116, 1.48, 44, 26, 15],
[33, 6, 29, 0.34, 13, 5, 16],
[94, 66, 110, 1.54, 62, 31, 17],
[186, 142, 192, 3.88, 93, 79, 18],
[57, 31, 54, 0.96, 32, 14, 19],
[22, 8, 17, 0.48, 23, 10, 20],
[39, 15, 36, 0.61, 29, 13, 21],
[94, 69, 114, 2.08, 73, 39, 22],
[99, 73, 110, 2.43, 76, 48, 23],
[31, 12, 30, 0.5, 32, 16, 24],
[42, 27, 43, 1, 53, 22, 25],
[154, 117, 157, 3.05, 92, 58, 26],
[234, 185, 230, 4.09, 123, 69, 27],
[160, 120, 186, 2.77, 91, 50, 28],
[134, 96, 165, 2.76, 83, 41, 29],
[52, 24, 60, 1.03, 50, 21, 30],
[46, 5, 49, 0.28, 10, 6, 31]
];
const dataGZ = [
[26, 37, 27, 1.163, 27, 13, 1],
[85, 62, 71, 1.195, 60, 8, 2],
[78, 38, 74, 1.363, 37, 7, 3],
[21, 21, 36, 0.634, 40, 9, 4],
[41, 42, 46, 0.915, 81, 13, 5],
[56, 52, 69, 1.067, 92, 16, 6],
[64, 30, 28, 0.924, 51, 2, 7],
[55, 48, 74, 1.236, 75, 26, 8],
[76, 85, 113, 1.237, 114, 27, 9],
[91, 81, 104, 1.041, 56, 40, 10],
[84, 39, 60, 0.964, 25, 11, 11],
[64, 51, 101, 0.862, 58, 23, 12],
[70, 69, 120, 1.198, 65, 36, 13],
[77, 105, 178, 2.549, 64, 16, 14],
[109, 68, 87, 0.996, 74, 29, 15],
[73, 68, 97, 0.905, 51, 34, 16],
[54, 27, 47, 0.592, 53, 12, 17],
[51, 61, 97, 0.811, 65, 19, 18],
[91, 71, 121, 1.374, 43, 18, 19],
[73, 102, 182, 2.787, 44, 19, 20],
[73, 50, 76, 0.717, 31, 20, 21],
[84, 94, 140, 2.238, 68, 18, 22],
[93, 77, 104, 1.165, 53, 7, 23],
[99, 130, 227, 3.97, 55, 15, 24],
[146, 84, 139, 1.094, 40, 17, 25],
[113, 108, 137, 1.481, 48, 15, 26],
[81, 48, 62, 1.619, 26, 3, 27],
[56, 48, 68, 1.336, 37, 9, 28],
[82, 92, 174, 3.29, 0, 13, 29],
[106, 116, 188, 3.628, 101, 16, 30],
[118, 50, 0, 1.383, 76, 11, 31]
];
const dataSH = [
[91, 45, 125, 0.82, 34, 23, 1],
[65, 27, 78, 0.86, 45, 29, 2],
[83, 60, 84, 1.09, 73, 27, 3],
[109, 81, 121, 1.28, 68, 51, 4],
[106, 77, 114, 1.07, 55, 51, 5],
[109, 81, 121, 1.28, 68, 51, 6],
[106, 77, 114, 1.07, 55, 51, 7],
[89, 65, 78, 0.86, 51, 26, 8],
[53, 33, 47, 0.64, 50, 17, 9],
[80, 55, 80, 1.01, 75, 24, 10],
[117, 81, 124, 1.03, 45, 24, 11],
[99, 71, 142, 1.1, 62, 42, 12],
[95, 69, 130, 1.28, 74, 50, 13],
[116, 87, 131, 1.47, 84, 40, 14],
[108, 80, 121, 1.3, 85, 37, 15],
[134, 83, 167, 1.16, 57, 43, 16],
[79, 43, 107, 1.05, 59, 37, 17],
[71, 46, 89, 0.86, 64, 25, 18],
[97, 71, 113, 1.17, 88, 31, 19],
[84, 57, 91, 0.85, 55, 31, 20],
[87, 63, 101, 0.9, 56, 41, 21],
[104, 77, 119, 1.09, 73, 48, 22],
[87, 62, 100, 1, 72, 28, 23],
[168, 128, 172, 1.49, 97, 56, 24],
[65, 45, 51, 0.74, 39, 17, 25],
[39, 24, 38, 0.61, 47, 17, 26],
[39, 24, 39, 0.59, 50, 19, 27],
[93, 68, 96, 1.05, 79, 29, 28],
[188, 143, 197, 1.66, 99, 51, 29],
[174, 131, 174, 1.55, 108, 50, 30],
[187, 143, 201, 1.39, 89, 53, 31]
];
const lineStyle = {
width: 1,
opacity: 0.5
};
const options = {
backgroundColor: '#161627',
title: {
text: 'AQI - Radar',
left: 'center',
textStyle: {
color: '#eee'
}
},
legend: {
show:false,
bottom: 5,
data: ['Beijing', 'Shanghai', 'Guangzhou'],
itemGap: 20,
textStyle: {
color: '#fff',
fontSize: 14
let props = defineProps({
className: {
type: String,
default: 'chart',
},
selectedMode: 'single'
},
radar: {
indicator: [
{ name: 'AQI', max: 300,min:1 },
{ name: 'PM2.5', max: 250,min:1 },
{ name: 'PM10', max: 300,min:1 },
{ name: 'CO', max: 5,min:1 },
{ name: 'NO2', max: 200,min:1 },
{ name: 'SO2', max: 100,min:1 }
],
shape: 'circle',
splitNumber: 5,
axisName: {
color: 'rgb(238, 197, 102)'
config: {
type: Object,
default: () => {},
},
splitLine: {
lineStyle: {
color: [
'rgba(238, 197, 102, 0.1)',
'rgba(238, 197, 102, 0.2)',
'rgba(238, 197, 102, 0.4)',
'rgba(238, 197, 102, 0.6)',
'rgba(238, 197, 102, 0.8)',
'rgba(238, 197, 102, 1)'
].reverse()
}
id: {
type: String,
default: 'chart',
},
splitArea: {
show: false
width: {
type: String,
default: '200px',
},
axisLine: {
lineStyle: {
color: 'rgba(238, 197, 102, 0.5)'
}
}
},
series: [
{
name: 'Beijing',
type: 'radar',
lineStyle: lineStyle,
data: dataBJ,
symbol: 'none',
itemStyle: {
color: '#F9713C'
},
areaStyle: {
opacity: 0.1
}
height: {
type: String,
default: '200px',
},
{
name: 'Shanghai',
type: 'radar',
lineStyle: lineStyle,
data: dataSH,
symbol: 'none',
itemStyle: {
color: '#B3E4A1'
},
areaStyle: {
opacity: 0.05
}
},
{
name: 'Guangzhou',
type: 'radar',
lineStyle: lineStyle,
data: dataGZ,
symbol: 'none',
itemStyle: {
color: 'rgb(238, 197, 102)'
},
areaStyle: {
opacity: 0.05
}
}
]
};
let chart:EChartsType;
const initChart =()=> {
let chart = echarts.init(document.getElementById(props.id))
chart.setOption(options)
return chart
}
onMounted(()=>{
chart = initChart()
window.addEventListener('resize',function (){
chart&&chart.resize()
})
const dataBJ = [
[55, 9, 56, 0.46, 18, 6, 1],
[25, 11, 21, 0.65, 34, 9, 2],
[56, 7, 63, 0.3, 14, 5, 3],
[33, 7, 29, 0.33, 16, 6, 4],
[42, 24, 44, 0.76, 40, 16, 5],
[82, 58, 90, 1.77, 68, 33, 6],
[74, 49, 77, 1.46, 48, 27, 7],
[78, 55, 80, 1.29, 59, 29, 8],
[267, 216, 280, 4.8, 108, 64, 9],
[185, 127, 216, 2.52, 61, 27, 10],
[39, 19, 38, 0.57, 31, 15, 11],
[41, 11, 40, 0.43, 21, 7, 12],
[64, 38, 74, 1.04, 46, 22, 13],
[108, 79, 120, 1.7, 75, 41, 14],
[108, 63, 116, 1.48, 44, 26, 15],
[33, 6, 29, 0.34, 13, 5, 16],
[94, 66, 110, 1.54, 62, 31, 17],
[186, 142, 192, 3.88, 93, 79, 18],
[57, 31, 54, 0.96, 32, 14, 19],
[22, 8, 17, 0.48, 23, 10, 20],
[39, 15, 36, 0.61, 29, 13, 21],
[94, 69, 114, 2.08, 73, 39, 22],
[99, 73, 110, 2.43, 76, 48, 23],
[31, 12, 30, 0.5, 32, 16, 24],
[42, 27, 43, 1, 53, 22, 25],
[154, 117, 157, 3.05, 92, 58, 26],
[234, 185, 230, 4.09, 123, 69, 27],
[160, 120, 186, 2.77, 91, 50, 28],
[134, 96, 165, 2.76, 83, 41, 29],
[52, 24, 60, 1.03, 50, 21, 30],
[46, 5, 49, 0.28, 10, 6, 31],
]
})
const dataGZ = [
[26, 37, 27, 1.163, 27, 13, 1],
[85, 62, 71, 1.195, 60, 8, 2],
[78, 38, 74, 1.363, 37, 7, 3],
[21, 21, 36, 0.634, 40, 9, 4],
[41, 42, 46, 0.915, 81, 13, 5],
[56, 52, 69, 1.067, 92, 16, 6],
[64, 30, 28, 0.924, 51, 2, 7],
[55, 48, 74, 1.236, 75, 26, 8],
[76, 85, 113, 1.237, 114, 27, 9],
[91, 81, 104, 1.041, 56, 40, 10],
[84, 39, 60, 0.964, 25, 11, 11],
[64, 51, 101, 0.862, 58, 23, 12],
[70, 69, 120, 1.198, 65, 36, 13],
[77, 105, 178, 2.549, 64, 16, 14],
[109, 68, 87, 0.996, 74, 29, 15],
[73, 68, 97, 0.905, 51, 34, 16],
[54, 27, 47, 0.592, 53, 12, 17],
[51, 61, 97, 0.811, 65, 19, 18],
[91, 71, 121, 1.374, 43, 18, 19],
[73, 102, 182, 2.787, 44, 19, 20],
[73, 50, 76, 0.717, 31, 20, 21],
[84, 94, 140, 2.238, 68, 18, 22],
[93, 77, 104, 1.165, 53, 7, 23],
[99, 130, 227, 3.97, 55, 15, 24],
[146, 84, 139, 1.094, 40, 17, 25],
[113, 108, 137, 1.481, 48, 15, 26],
[81, 48, 62, 1.619, 26, 3, 27],
[56, 48, 68, 1.336, 37, 9, 28],
[82, 92, 174, 3.29, 0, 13, 29],
[106, 116, 188, 3.628, 101, 16, 30],
[118, 50, 0, 1.383, 76, 11, 31],
]
const dataSH = [
[91, 45, 125, 0.82, 34, 23, 1],
[65, 27, 78, 0.86, 45, 29, 2],
[83, 60, 84, 1.09, 73, 27, 3],
[109, 81, 121, 1.28, 68, 51, 4],
[106, 77, 114, 1.07, 55, 51, 5],
[109, 81, 121, 1.28, 68, 51, 6],
[106, 77, 114, 1.07, 55, 51, 7],
[89, 65, 78, 0.86, 51, 26, 8],
[53, 33, 47, 0.64, 50, 17, 9],
[80, 55, 80, 1.01, 75, 24, 10],
[117, 81, 124, 1.03, 45, 24, 11],
[99, 71, 142, 1.1, 62, 42, 12],
[95, 69, 130, 1.28, 74, 50, 13],
[116, 87, 131, 1.47, 84, 40, 14],
[108, 80, 121, 1.3, 85, 37, 15],
[134, 83, 167, 1.16, 57, 43, 16],
[79, 43, 107, 1.05, 59, 37, 17],
[71, 46, 89, 0.86, 64, 25, 18],
[97, 71, 113, 1.17, 88, 31, 19],
[84, 57, 91, 0.85, 55, 31, 20],
[87, 63, 101, 0.9, 56, 41, 21],
[104, 77, 119, 1.09, 73, 48, 22],
[87, 62, 100, 1, 72, 28, 23],
[168, 128, 172, 1.49, 97, 56, 24],
[65, 45, 51, 0.74, 39, 17, 25],
[39, 24, 38, 0.61, 47, 17, 26],
[39, 24, 39, 0.59, 50, 19, 27],
[93, 68, 96, 1.05, 79, 29, 28],
[188, 143, 197, 1.66, 99, 51, 29],
[174, 131, 174, 1.55, 108, 50, 30],
[187, 143, 201, 1.39, 89, 53, 31],
]
const lineStyle = {
width: 1,
opacity: 0.5,
}
const options = {
backgroundColor: '#161627',
title: {
text: 'AQI - Radar',
left: 'center',
textStyle: {
color: '#eee',
},
},
legend: {
show: false,
bottom: 5,
data: ['Beijing', 'Shanghai', 'Guangzhou'],
itemGap: 20,
textStyle: {
color: '#fff',
fontSize: 14,
},
selectedMode: 'single',
},
radar: {
indicator: [
{ name: 'AQI', max: 300, min: 1 },
{ name: 'PM2.5', max: 250, min: 1 },
{ name: 'PM10', max: 300, min: 1 },
{ name: 'CO', max: 5, min: 1 },
{ name: 'NO2', max: 200, min: 1 },
{ name: 'SO2', max: 100, min: 1 },
],
shape: 'circle',
splitNumber: 5,
axisName: {
color: 'rgb(238, 197, 102)',
},
splitLine: {
lineStyle: {
color: [
'rgba(238, 197, 102, 0.1)',
'rgba(238, 197, 102, 0.2)',
'rgba(238, 197, 102, 0.4)',
'rgba(238, 197, 102, 0.6)',
'rgba(238, 197, 102, 0.8)',
'rgba(238, 197, 102, 1)',
].reverse(),
},
},
splitArea: {
show: false,
},
axisLine: {
lineStyle: {
color: 'rgba(238, 197, 102, 0.5)',
},
},
},
series: [
{
name: 'Beijing',
type: 'radar',
lineStyle: lineStyle,
data: dataBJ,
symbol: 'none',
itemStyle: {
color: '#F9713C',
},
areaStyle: {
opacity: 0.1,
},
},
{
name: 'Shanghai',
type: 'radar',
lineStyle: lineStyle,
data: dataSH,
symbol: 'none',
itemStyle: {
color: '#B3E4A1',
},
areaStyle: {
opacity: 0.05,
},
},
{
name: 'Guangzhou',
type: 'radar',
lineStyle: lineStyle,
data: dataGZ,
symbol: 'none',
itemStyle: {
color: 'rgb(238, 197, 102)',
},
areaStyle: {
opacity: 0.05,
},
},
],
}
let chart: EChartsType
const initChart = () => {
let chart = echarts.init(document.getElementById(props.id))
chart.setOption(options)
return chart
}
onMounted(() => {
chart = initChart()
window.addEventListener('resize', function () {
chart && chart.resize()
})
})
</script>

View File

@ -1,85 +1,84 @@
<template>
<div :id="id" :class="className" :style="{height:height,width:width}" />
<div :id="id" :class="className" :style="{ height: height, width: width }" />
</template>
<script lang="ts" setup>
import * as echarts from "echarts";
import {EChartsType} from "echarts/core";
import {onMounted} from "vue";
import * as echarts from 'echarts'
import { EChartsType } from 'echarts/core'
import { onMounted } from 'vue'
let props = defineProps({
className: {
type: String,
default: 'chart'
},
config:{
type: Object,
default: ()=>{}
},
id: {
type: String,
default: 'chart'
},
width: {
type: String,
default: '200px'
},
height: {
type: String,
default: '200px'
}
})
const options = {
grid: {
top: 10,
left: '2%',
right: '2%',
bottom: '2%',
containLabel: true
},
xAxis: {},
yAxis: {},
series: [
{
symbolSize: 20,
data: [
[10.0, 8.04],
[8.07, 6.95],
[13.0, 7.58],
[9.05, 8.81],
[11.0, 8.33],
[14.0, 7.66],
[13.4, 6.81],
[10.0, 6.33],
[14.0, 8.96],
[12.5, 6.82],
[9.15, 7.2],
[11.5, 7.2],
[3.03, 4.23],
[12.2, 7.83],
[2.02, 4.47],
[1.05, 3.33],
[4.05, 4.96],
[6.03, 7.24],
[12.0, 6.26],
[12.0, 8.84],
[7.08, 5.82],
[5.02, 5.68]
],
type: 'scatter'
}
]
};
let chart:EChartsType;
const initChart =()=> {
let chart = echarts.init(document.getElementById(props.id))
chart.setOption(options)
return chart
}
onMounted(()=>{
chart = initChart()
window.addEventListener('resize',function (){
chart&&chart.resize()
let props = defineProps({
className: {
type: String,
default: 'chart',
},
config: {
type: Object,
default: () => {},
},
id: {
type: String,
default: 'chart',
},
width: {
type: String,
default: '200px',
},
height: {
type: String,
default: '200px',
},
})
const options = {
grid: {
top: 10,
left: '2%',
right: '2%',
bottom: '2%',
containLabel: true,
},
xAxis: {},
yAxis: {},
series: [
{
symbolSize: 20,
data: [
[10.0, 8.04],
[8.07, 6.95],
[13.0, 7.58],
[9.05, 8.81],
[11.0, 8.33],
[14.0, 7.66],
[13.4, 6.81],
[10.0, 6.33],
[14.0, 8.96],
[12.5, 6.82],
[9.15, 7.2],
[11.5, 7.2],
[3.03, 4.23],
[12.2, 7.83],
[2.02, 4.47],
[1.05, 3.33],
[4.05, 4.96],
[6.03, 7.24],
[12.0, 6.26],
[12.0, 8.84],
[7.08, 5.82],
[5.02, 5.68],
],
type: 'scatter',
},
],
}
let chart: EChartsType
const initChart = () => {
let chart = echarts.init(document.getElementById(props.id))
chart.setOption(options)
return chart
}
onMounted(() => {
chart = initChart()
window.addEventListener('resize', function () {
chart && chart.resize()
})
})
})
</script>

View File

@ -5,20 +5,18 @@
</template>
<script lang="ts" setup>
import Chart from '@/components/Charts/LineMarker.vue'
import Chart from '@/components/Charts/LineMarker.vue'
// export default {
// // name: 'LineChart',
// // components: { Chart }
// }
// export default {
// // name: 'LineChart',
// // components: { Chart }
// }
</script>
<style scoped>
.chart-container{
position: relative;
width: 100%;
height: calc(100vh - 130px);
}
.chart-container {
position: relative;
width: 100%;
height: calc(100vh - 130px);
}
</style>

View File

@ -1,17 +1,15 @@
<template>
<div class="echarts-map">
<map-charts height="100%" width="100%" id="sankey"/>
<map-charts height="100%" width="100%" id="sankey" />
</div>
</template>
<script setup lang="ts">
import MapCharts from './components/map/index.vue'
import MapCharts from './components/map/index.vue'
</script>
<style>
.echarts-map{
height: calc(100vh - 150px);
}
.echarts-map {
height: calc(100vh - 150px);
}
</style>

View File

@ -1,31 +1,30 @@
<template>
<div class="echarts-map">
<el-card class="info">Echarts 实现飞线图地图增加图标高亮</el-card>
<migration-charts height="100%" width="100%" id="migration"/>
<migration-charts height="100%" width="100%" id="migration" />
</div>
</template>
<script setup lang="ts">
import MigrationCharts from './components/migration/index.vue'
import MigrationCharts from './components/migration/index.vue'
</script>
<style lang="scss" scoped>
.echarts-map{
box-sizing: border-box;
width: 100%;
overflow: hidden;
height: calc(100vh - 93px);
position: relative;
.info{
position: absolute;
left: 0;
.echarts-map {
box-sizing: border-box;
width: 100%;
font-weight: bold;
z-index: 999;
overflow: hidden;
height: calc(100vh - 93px);
position: relative;
.info {
position: absolute;
left: 0;
width: 100%;
font-weight: bold;
z-index: 999;
}
::v-deep(.el-card) {
border-radius: 0;
}
}
::v-deep(.el-card){
border-radius: 0;
}
}
</style>

View File

@ -1,25 +1,25 @@
<template>
<u-container-layout style="width: 100%;">
<u-container-layout style="width: 100%">
<el-row class="row-bg" :gutter="10">
<el-col :xs="24" :sm="12" :lg="8">
<el-card class="box-card">
<template #header>
<div class="card-header">
<span>折线图</span>
</div>
</template>
<line-charts height="200px" width="100%"/>
</el-card>
<template #header>
<div class="card-header">
<span>折线图</span>
</div>
</template>
<line-charts height="200px" width="100%" />
</el-card>
</el-col>
<el-col :xs="24" :sm="12" :lg="8">
<el-card class="box-card">
<template #header>
<div class="card-header">
<span>柱状图</span>
</div>
</template>
<bar-charts height="200px" width="100%" id="bar"/>
</el-card></el-col>
<template #header>
<div class="card-header">
<span>柱状图</span>
</div>
</template>
<bar-charts height="200px" width="100%" id="bar" /> </el-card
></el-col>
<el-col :xs="24" :sm="12" :lg="8">
<el-card class="box-card">
<template #header>
@ -27,7 +27,7 @@
<span>饼图</span>
</div>
</template>
<pie-charts height="200px" width="100%" id="pie"/>
<pie-charts height="200px" width="100%" id="pie" />
</el-card>
</el-col>
<el-col :xs="24" :sm="12" :lg="8">
@ -37,7 +37,7 @@
<span>散点图</span>
</div>
</template>
<scatter-charts height="200px" width="100%" id="scatter"/>
<scatter-charts height="200px" width="100%" id="scatter" />
</el-card>
</el-col>
<el-col :xs="24" :sm="12" :lg="8">
@ -47,7 +47,7 @@
<span>仪表盘</span>
</div>
</template>
<gauge-charts height="200px" width="100%" id="gauge"/>
<gauge-charts height="200px" width="100%" id="gauge" />
</el-card>
</el-col>
<el-col :xs="24" :sm="12" :lg="8">
@ -57,7 +57,7 @@
<span>漏斗图</span>
</div>
</template>
<funnel-charts height="200px" width="100%" id="funnel"/>
<funnel-charts height="200px" width="100%" id="funnel" />
</el-card>
</el-col>
<el-col :xs="24" :sm="12" :lg="8">
@ -67,19 +67,19 @@
<span>K 线图</span>
</div>
</template>
<candlestick-charts height="200px" width="100%" id="candlestick"/>
<candlestick-charts height="200px" width="100%" id="candlestick" />
</el-card>
</el-col>
<!-- <el-col :xs="24" :sm="12" :lg="8">-->
<!-- <el-card class="box-card">-->
<!-- <template #header>-->
<!-- <div class="card-header">-->
<!-- <span>雷达图</span>-->
<!-- </div>-->
<!-- </template>-->
<!-- <radar-charts height="200px" width="100%" id="radar"/>-->
<!-- </el-card>-->
<!-- </el-col>-->
<!-- <el-col :xs="24" :sm="12" :lg="8">-->
<!-- <el-card class="box-card">-->
<!-- <template #header>-->
<!-- <div class="card-header">-->
<!-- <span>雷达图</span>-->
<!-- </div>-->
<!-- </template>-->
<!-- <radar-charts height="200px" width="100%" id="radar"/>-->
<!-- </el-card>-->
<!-- </el-col>-->
<el-col :xs="24" :sm="12" :lg="8">
<el-card class="box-card">
<template #header>
@ -87,7 +87,7 @@
<span>雷达图</span>
</div>
</template>
<graph-charts height="200px" width="100%" id="graph"/>
<graph-charts height="200px" width="100%" id="graph" />
</el-card>
</el-col>
@ -98,13 +98,10 @@
<span>虚线柱状图效果</span>
</div>
</template>
<pictorial-bar height="200px" width="100%" id="pictorial"/>
<pictorial-bar height="200px" width="100%" id="pictorial" />
</el-card>
</el-col>
</el-row>
</u-container-layout>
</template>
<script setup lang="ts">
@ -118,28 +115,26 @@
import RadarCharts from './components/simple/radar.vue'
import GraphCharts from './components/simple/graph.vue'
import PictorialBarCharts from './components/simple/pictorialBar.vue'
import PictorialBar from "@/views/charts/components/simple/pictorialBar.vue";
import PictorialBar from '@/views/charts/components/simple/pictorialBar.vue'
</script>
<style>
.card-header {
display: flex;
justify-content: space-between;
align-items: center;
}
.card-header {
display: flex;
justify-content: space-between;
align-items: center;
}
.text {
font-size: 14px;
}
.text {
font-size: 14px;
}
.item {
margin-bottom: 18px;
}
.item {
margin-bottom: 18px;
}
.box-card {
margin-bottom: 10px;
width: 100%;
}
.box-card {
margin-bottom: 10px;
width: 100%;
}
</style>

View File

@ -1,15 +1,15 @@
export const chatData = [
{
is_self:0,
created_at:'2022-03-11',
content:'hello 你好呀!',
id:1
},
{
is_self:1,
created_at:'2022-03-11',
content:'hello 你好呀!',
id:2,
type:1, // 文字
}
{
is_self: 0,
created_at: '2022-03-11',
content: 'hello 你好呀!',
id: 1,
},
{
is_self: 1,
created_at: '2022-03-11',
content: 'hello 你好呀!',
id: 2,
type: 1, // 文字
},
]

View File

@ -1,12 +1,12 @@
<template>
<div class="g-container-chat">
<div class="g-layout-content-center" style="width:100%;" ref="chatContentBoxs">
<div v-for="item,index in chatDatas" :key="item.id" style="padding-top: 15px;">
<div class="from_user_info" v-if="item.is_self===0">
<div class="g-layout-content-center" style="width: 100%" ref="chatContentBoxs">
<div v-for="(item, index) in chatDatas" :key="item.id" style="padding-top: 15px">
<div class="from_user_info" v-if="item.is_self === 0">
<div class="contact-nickname">{{ item.created_at }} 林峰</div>
<div class="receive-message-wrap">
<div class="avatar-show">
<img src="@/assets/image/avator.png"/>
<img src="@/assets/image/avator.png" />
</div>
<div style="position: relative; display: flex">
<div class="receive-message-info" v-html="item.content"></div>
@ -17,53 +17,56 @@
<div class="contact-nickname">{{ item.created_at }} 林峰</div>
<div class="receive-message-wrap public-show-pic">
<div style="position: relative; display: flex">
<div class="receive-message-info" v-if="item.type==1">
<div class="receive-message-info" v-if="item.type == 1">
<div class="text-content" v-html="item.content"></div>
</div>
<div class="public-show-pic" v-else-if="item.type===2">
<el-image :src="item.content" :preview-src-list="[item.content]" style="max-width:200px;" :data-resid="Date.now()"/>
<div class="public-show-pic" v-else-if="item.type === 2">
<el-image
:src="item.content"
:preview-src-list="[item.content]"
style="max-width: 200px"
:data-resid="Date.now()"
/>
</div>
</div>
<div class="avatar-show">
<img src="@/assets/image/avator.png"/>
<img src="@/assets/image/avator.png" />
</div>
</div>
</div>
</div>
</div>
<u-toolbar @insert="insertInput" @upload="upload"/>
<u-toolbar @insert="insertInput" @upload="upload" />
<div
@blur="contentBlur"
ref="contenteditableInputs"
class="g-chat-container-footer-input"
contenteditable=true></div>
@blur="contentBlur"
ref="contenteditableInputs"
class="g-chat-container-footer-input"
contenteditable="true"
></div>
<div class="g-chat-container-footer-btn">
<div class="" style="margin-right:10px">
Ctrl+V粘贴, Ctrl+Enter换行
</div>
<div class="" style="margin-right: 10px"> Ctrl+V粘贴, Ctrl+Enter换行 </div>
<el-button @click="sendInfoAction">发送</el-button>
</div>
</div>
</template>
<script lang="ts" setup>
import {onMounted,ref,nextTick} from 'vue'
import { onMounted, ref, nextTick } from 'vue'
import UToolbar from '../u-toolbar/index.vue'
import defalutAvator from '@/assets/image/avator.png'
import {chatData} from './chat.js'
import {ElMessage} from "element-plus";
import dayjs from "dayjs";
import { chatData } from './chat.js'
import { ElMessage } from 'element-plus'
import dayjs from 'dayjs'
const range = ref<HTMLElement|null>(null)
const range = ref<HTMLElement | null>(null)
const selection = ref<any>(null)
const chatDatas = ref<any>(chatData)
const defalutAvatorImg = ref<any>(defalutAvator)
const contenteditableInputs = ref<HTMLElement|null>(null)
const chatContentBoxs = ref<HTMLElement|null>(null)
const contenteditableInputs = ref<HTMLElement | null>(null)
const chatContentBoxs = ref<HTMLElement | null>(null)
const preview_src_data = ref<string[]>([])
const focusContentEditable = ()=>{
const focusContentEditable = () => {
const editor = contenteditableInputs.value
editor?.focus()
//
@ -71,13 +74,15 @@
range.value = selection.value.getRangeAt(0)
}
const keepLastIndex = (obj)=> {
if (window.getSelection) { // ie11 10 9 ff safari
const keepLastIndex = (obj) => {
if (window.getSelection) {
// ie11 10 9 ff safari
obj.focus() // ff
let range = window.getSelection() // range
range.selectAllChildren(obj) // range obj
range.collapseToEnd() //
} else if (document.selection) { // ie10 9 8 7 6 5
} else if (document.selection) {
// ie10 9 8 7 6 5
let range = document.selection.createRange() //
// var range = document.body.createTextRange();
range.moveToElementText(obj) // rangeobj
@ -86,7 +91,7 @@
}
}
const setCursor =(node?:any, before?:boolean)=> {
const setCursor = (node?: any, before?: boolean) => {
/**
* node 为传入的节点不传则foucs到之前保存的位置
* before 控制折叠方向
@ -106,7 +111,7 @@
selection.value.addRange(range.value)
}
}
const contentBlur = ()=>{
const contentBlur = () => {
/**
* 每次焦点移出都要保存一次当前 range 后面好放回来
* 由于输入框以外的点击都会使输入框失去焦点不知道会有什么操作故勤保存
@ -118,7 +123,7 @@
* @func 聊天框聚焦
* @param e
*/
const contentFoucs = (e)=> {
const contentFoucs = (e) => {
/**
* range更新到点击的位置
* 点到图片就根据点击位置和图片大小设置一个合理的位置(前或后)
@ -131,30 +136,30 @@
}
}
const insertInput = (node?:any,type?:string)=>{
if(type==='IMG'){
const insertInput = (node?: any, type?: string) => {
if (type === 'IMG') {
range.value.insertNode(node)
setCursor(node, false)
}else {
} else {
setCursor()
}
}
const sendMessageData = (content:string,type:number=1)=>{
const day = dayjs().format('YYYY-MM-DD');
return{
is_self:1,
created_at:day,
const sendMessageData = (content: string, type = 1) => {
const day = dayjs().format('YYYY-MM-DD')
return {
is_self: 1,
created_at: day,
content,
type,
id:Date.now()+Math.random()
id: Date.now() + Math.random(),
}
}
const getPreviewList = ()=>{
const getPreviewList = () => {
preview_src_data.value = []
nextTick(()=>{
chatDatas.value.forEach(item=>{
nextTick(() => {
chatDatas.value.forEach((item) => {
if (item.type === 2) {
preview_src_data.value.push(item.content)
}
@ -162,7 +167,7 @@
})
}
const upload = (newBase64:string)=>{
const upload = (newBase64: string) => {
const value = contenteditableInputs.value
let image = new Image()
image.onload = function () {
@ -174,7 +179,7 @@
image.width = 100
}
const scrollHeight = ()=>{
const scrollHeight = () => {
nextTick(() => {
setTimeout(() => {
chatContentBoxs.value.scrollTop = chatContentBoxs.value.scrollHeight
@ -182,33 +187,33 @@
})
}
const sendInfoAction = ()=>{
const sendInfoAction = () => {
const value = contenteditableInputs.value.innerHTML
console.log('value===',value)
if(!value){
console.log('value===', value)
if (!value) {
setCursor()
return ElMessage.error('请填写发送内容')
}
let reg = /<img.*?src="(.*?)".*?title="(.*?)".*?>/ig
let reg1 = /<img.*?src="(.*?)".*?insert="(.*?)">/ig
let reg = /<img.*?src="(.*?)".*?title="(.*?)".*?>/gi
let reg1 = /<img.*?src="(.*?)".*?insert="(.*?)">/gi
let content = value.replace(reg, '[$2]')
let data = []
let flag = content.match(reg1)
console.log('content',flag)
if(flag){
console.log('content', flag)
if (flag) {
//
let content2 = content.replace(reg1, (item, $1) => {
return `/b/~${$1}/b/~`
})
let splitImg = content2.split('/b/~')
for(let item of splitImg){
if(item){
chatDatas.value.push(sendMessageData(item,2))
for (let item of splitImg) {
if (item) {
chatDatas.value.push(sendMessageData(item, 2))
}
}
}else {
} else {
data = sendMessageData(value)
chatDatas.value.push(data)
}
@ -216,248 +221,247 @@
getPreviewList()
contenteditableInputs.value.innerHTML = ''
console.log('content--',chatDatas.value)
console.log('content--', chatDatas.value)
scrollHeight()
}
onMounted(()=>{
nextTick(()=>{
onMounted(() => {
nextTick(() => {
focusContentEditable()
})
})
</script>
<style lang="scss" scoped>
.g-layout-content-center{
min-height: 300px;
padding:0 15px 15px;
flex: auto;
overflow: auto;
max-height: 400px;
.g-layout-content-center {
min-height: 300px;
padding: 0 15px 15px;
flex: auto;
overflow: auto;
max-height: 400px;
background: #f7f6f4;
border-right: 1px solid #ededed;
border-bottom: 1px solid #ededed;
box-sizing: border-box;
}
[contenteditable]:focus{outline: none;}
.g-chat-container-footer-input{
word-break: break-all;
padding: 8px;
white-space: pre-wrap;
overflow: auto;
min-height: 120px;
flex: 1;
background: #f7f6f4;
::v-deep(.at-logo){
padding-right: 5px;
vertical-align: text-bottom;
background: #f7f6f4;
border-right: 1px solid #ededed;
border-bottom: 1px solid #ededed;
box-sizing: border-box;
}
}
.g-chat-container-footer-btn{
height: 50px;
background: #f7f6f4;
display: flex;
align-items: center;
justify-content: flex-end;
flex-shrink: 0;
::v-deep(.el-button){
padding: 8px 20px;
margin-right: 15px;
[contenteditable]:focus {
outline: none;
}
}
.g-layout-content-chat-util{
height: 46px;
display: flex;
flex-shrink: 0;
justify-content: space-between;
position: relative;
border-bottom: 1px solid #ebebeb;
background: white;
.item-left{
.g-chat-container-footer-input {
word-break: break-all;
padding: 8px;
white-space: pre-wrap;
overflow: auto;
min-height: 120px;
flex: 1;
background: #f7f6f4;
::v-deep(.at-logo) {
padding-right: 5px;
vertical-align: text-bottom;
}
}
.g-chat-container-footer-btn {
height: 50px;
background: #f7f6f4;
display: flex;
align-items: center;
justify-content: flex-end;
flex-shrink: 0;
::v-deep(.el-button) {
padding: 8px 20px;
margin-right: 15px;
}
}
.upload-picture{
cursor: pointer;
.g-layout-content-chat-util {
height: 46px;
display: flex;
align-items: center;
justify-content: center;
height: 100%;
width: 40px;
}
.screenshot-upload{
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
height: 100%;
width: 40px;
}
.recoding-chatbox{
flex-shrink: 0;
justify-content: space-between;
position: relative;
}
.emoje{
display: flex;
align-items: center;
height: 100%;
justify-content: center;
width: 40px;
font-size: 25px;
cursor: pointer;
color: grey;
}
.upload-picture{
cursor: pointer;
display: flex;
align-items: center;
height: 100%;
width: 40px;
justify-content: center;
}
.emoje-border-wrap{
top: -364px;
left: 0;
position: absolute;
width: 372px;
padding: 10px;
z-index: 9;
border: 1px solid #D9D9D9;
background-color: #fff;
overflow: hidden;
box-shadow: 0 0 20px rgba(0,0,0,.2);
.title-emoje{
border-bottom: 1px solid #ebebeb;
background: white;
.item-left {
display: flex;
align-items: center;
}
.upload-picture {
cursor: pointer;
float: left;
border: 1px solid #e8e8e8;
height: 32px;
width: 32px;
overflow: hidden;
display: flex;
align-items: center;
justify-content: center;
margin: -1px 0 0 -1px;
//padding: 4px 2px;
text-align: center;
/*img{*/
/* width: 100%;*/
/* height: 100%;*/
/*}*/
height: 100%;
width: 40px;
}
}
}
.from_user_info{
width: 100%;
// overflow: hidden;
float: left;
font-size: 12px;
display: flex;
flex-direction: column;
margin-bottom: 10px;
::v-deep .share-link {
color: #000;
text-decoration: none;
section {
.screenshot-upload {
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
height: 100%;
width: 40px;
}
.clamp {
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
.recoding-chatbox {
position: relative;
}
.emoje {
display: flex;
align-items: center;
height: 100%;
justify-content: center;
width: 40px;
font-size: 25px;
cursor: pointer;
color: grey;
}
.upload-picture {
cursor: pointer;
display: flex;
align-items: center;
height: 100%;
width: 40px;
justify-content: center;
}
.emoje-border-wrap {
top: -364px;
left: 0;
position: absolute;
width: 372px;
padding: 10px;
z-index: 9;
border: 1px solid #d9d9d9;
background-color: #fff;
overflow: hidden;
}
.left-side {
flex: 1;
}
.right-side {
width: 60px;
margin-left: 20px;
img {
width: 100%;
box-shadow: 0 0 20px rgba(0, 0, 0, 0.2);
.title-emoje {
cursor: pointer;
float: left;
border: 1px solid #e8e8e8;
height: 32px;
width: 32px;
overflow: hidden;
display: flex;
align-items: center;
justify-content: center;
margin: -1px 0 0 -1px;
//padding: 4px 2px;
text-align: center;
/*img{*/
/* width: 100%;*/
/* height: 100%;*/
/*}*/
}
}
}
.receive-message-wrap{
.from_user_info {
width: 100%;
// overflow: hidden;
float: left;
font-size: 12px;
display: flex;
}
.text-content{
background: #fff;
word-break: break-all;
padding: 5px 10px;
max-width: 300px;
white-space: pre-wrap;
}
.receive-message-info{
background: white;
display: flex;
align-items: center;
padding: 0 5px;
border-radius: 4px;
}
.contact-nickname{
margin-bottom: 5px;
color: #b4b4b4;
}
.avatar-show{
flex-shrink:0 ;
width: 35px;
height: 35px;
margin-right: 10px;
border: 1px solid #e9e9e9;
img{
width: 100%;
height: 100%;
flex-direction: column;
margin-bottom: 10px;
::v-deep .share-link {
color: #000;
text-decoration: none;
section {
display: flex;
align-items: center;
}
.clamp {
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
overflow: hidden;
}
.left-side {
flex: 1;
}
.right-side {
width: 60px;
margin-left: 20px;
img {
width: 100%;
}
}
}
.receive-message-wrap {
display: flex;
}
.text-content {
background: #fff;
word-break: break-all;
padding: 5px 10px;
max-width: 300px;
white-space: pre-wrap;
}
.receive-message-info {
background: white;
display: flex;
align-items: center;
padding: 0 5px;
border-radius: 4px;
}
.contact-nickname {
margin-bottom: 5px;
color: #b4b4b4;
}
.avatar-show {
flex-shrink: 0;
width: 35px;
height: 35px;
margin-right: 10px;
border: 1px solid #e9e9e9;
img {
width: 100%;
height: 100%;
}
}
}
}
.ower-user_info{
font-size: 12px;
display: flex;
width: 100%;
float: right;
justify-content: flex-end;
flex-direction: column;
margin-top: 10px;
.text-content{
word-break: break-all;
padding: 5px;
white-space:pre-wrap;
max-width: 300px;
}
.receive-message-wrap{
.ower-user_info {
font-size: 12px;
display: flex;
width: 100%;
float: right;
justify-content: flex-end;
align-items: center
}
.receive-message-info{
background: #9eea6a;
display: flex;
align-items: center;
padding: 0 5px;
border-radius: 4px;
}
.contact-nickname{
text-align: right;
margin-bottom: 5px;
color: #b4b4b4;
}
.avatar-show{
flex-shrink:0 ;
width: 35px;
height: 35px;
margin-left: 10px;
border: 1px solid #e9e9e9;
img{
width: 100%;
height: 100%;
flex-direction: column;
margin-top: 10px;
.text-content {
word-break: break-all;
padding: 5px;
white-space: pre-wrap;
max-width: 300px;
}
.receive-message-wrap {
display: flex;
justify-content: flex-end;
align-items: center;
}
.receive-message-info {
background: #9eea6a;
display: flex;
align-items: center;
padding: 0 5px;
border-radius: 4px;
}
.contact-nickname {
text-align: right;
margin-bottom: 5px;
color: #b4b4b4;
}
.avatar-show {
flex-shrink: 0;
width: 35px;
height: 35px;
margin-left: 10px;
border: 1px solid #e9e9e9;
img {
width: 100%;
height: 100%;
}
}
}
}
</style>

View File

@ -1,22 +1,22 @@
<template>
<div class="g-layout-content-chat-util">
<div class="item-left">
<div class="emoje" title="选择表情" @click.stop="selectEmojiAction">
<img src="static/face/emoji-after.png" alt="" style="width:20px">
<img src="static/face/emoji-after.png" alt="" style="width: 20px" />
</div>
<div class="upload-picture" title="上传图片">
<el-upload action multiple :show-file-list="false" :before-upload="beforeUploadAction">
<el-icon style="font-size:20px"><FolderOpened/></el-icon>
<el-icon style="font-size: 20px"><FolderOpened /></el-icon>
</el-upload>
</div>
<div class="emoje-border-wrap" v-show="isShowEmoji">
<div class="title-emoje"
v-for="(item,index) in emojis"
@click.stop="selectSigleEmojeAction($event,item)"
:key="index">
<img :src="`static/face/${item}.png`" :title="item"/>
<div
class="title-emoje"
v-for="(item, index) in emojis"
@click.stop="selectSigleEmojeAction($event, item)"
:key="index"
>
<img :src="`static/face/${item}.png`" :title="item" />
</div>
</div>
</div>
@ -24,138 +24,135 @@
</template>
<script setup lang="ts">
import { ref,defineEmits,onMounted } from 'vue'
import {
FolderOpened
} from '@element-plus/icons-vue'
import {ElMessage} from "element-plus";
import { ref, defineEmits, onMounted } from 'vue'
import { FolderOpened } from '@element-plus/icons-vue'
import { ElMessage } from 'element-plus'
import emoji from '@/utils/emojis'
const emojis = ref<string[]>(emoji.imgs)
const isShowEmoji = ref<boolean>(false)
const emit = defineEmits(['insert','upload'])
const emit = defineEmits(['insert', 'upload'])
const selectSigleEmojeAction = (e, item) =>{
const selectSigleEmojeAction = (e, item) => {
if (e.target.tagName === 'IMG') {
let node = e.target.cloneNode(true)
node.title = item
emit('insert',node,'IMG')
emit('insert', node, 'IMG')
} else {
emit('insert',node)
emit('insert', node)
}
}
const selectEmojiAction =()=> {
const selectEmojiAction = () => {
isShowEmoji.value = true
emit('insert',null,null)
emit('insert', null, null)
}
const beforeUploadAction = (file, fileList)=>{
const beforeUploadAction = (file, fileList) => {
return new Promise((resolve, reject) => {
var reader = new FileReader()
let reg = (/\.jpg$|\.jpeg$|\.gif$|\.png$/i)
let reg = /\.jpg$|\.jpeg$|\.gif$|\.png$/i
reader.readAsDataURL(file)
let name = file.name
if(reg.test(name)){
reader.onload = (e:FileReader)=>{
if (reg.test(name)) {
reader.onload = (e: FileReader) => {
resolve(e.target.result)
emit('upload',e.target.result)
emit('upload', e.target.result)
}
}else{
} else {
ElMessage.error('请上传图片')
reject()
}
})
}
onMounted(()=>{
onMounted(() => {
window.onclick = function (event) {
isShowEmoji.value = false
}
})
</script>
<style lang="scss" scoped>
.g-layout-content-chat-util{
height: 46px;
display: flex;
flex-shrink: 0;
justify-content: space-between;
position: relative;
border-bottom: 1px solid #ebebeb;
background: white;
.item-left{
.g-layout-content-chat-util {
height: 46px;
display: flex;
align-items: center;
}
.upload-picture{
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
height: 100%;
width: 40px;
}
.screenshot-upload{
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
height: 100%;
width: 40px;
}
.recoding-chatbox{
flex-shrink: 0;
justify-content: space-between;
position: relative;
}
.emoje{
display: flex;
align-items: center;
height: 100%;
justify-content: center;
width: 40px;
font-size: 25px;
cursor: pointer;
color: grey;
}
.upload-picture{
cursor: pointer;
display: flex;
align-items: center;
height: 100%;
width: 40px;
justify-content: center;
}
.emoje-border-wrap{
top: -121px;
left: 0;
position: absolute;
width: 372px;
padding: 10px;
z-index: 9;
border: 1px solid #D9D9D9;
background-color: #fff;
overflow: hidden;
box-shadow: 0 0 20px rgba(0,0,0,.2);
.title-emoje{
border-bottom: 1px solid #ebebeb;
background: white;
.item-left {
display: flex;
align-items: center;
}
.upload-picture {
cursor: pointer;
float: left;
border: 1px solid #e8e8e8;
height: 32px;
width: 32px;
overflow: hidden;
display: flex;
align-items: center;
justify-content: center;
margin: -1px 0 0 -1px;
//padding: 4px 2px;
text-align: center;
/*img{*/
/* width: 100%;*/
/* height: 100%;*/
/*}*/
height: 100%;
width: 40px;
}
.screenshot-upload {
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
height: 100%;
width: 40px;
}
.recoding-chatbox {
position: relative;
}
.emoje {
display: flex;
align-items: center;
height: 100%;
justify-content: center;
width: 40px;
font-size: 25px;
cursor: pointer;
color: grey;
}
.upload-picture {
cursor: pointer;
display: flex;
align-items: center;
height: 100%;
width: 40px;
justify-content: center;
}
.emoje-border-wrap {
top: -121px;
left: 0;
position: absolute;
width: 372px;
padding: 10px;
z-index: 9;
border: 1px solid #d9d9d9;
background-color: #fff;
overflow: hidden;
box-shadow: 0 0 20px rgba(0, 0, 0, 0.2);
.title-emoje {
cursor: pointer;
float: left;
border: 1px solid #e8e8e8;
height: 32px;
width: 32px;
overflow: hidden;
display: flex;
align-items: center;
justify-content: center;
margin: -1px 0 0 -1px;
//padding: 4px 2px;
text-align: center;
/*img{*/
/* width: 100%;*/
/* height: 100%;*/
/*}*/
}
}
}
}
</style>

View File

@ -1,8 +1,10 @@
<template>
<u-container-layout>
<div>
<div style="margin-bottom: 15px">聊天内容框功能有发送emoji表情上传图片发送图片内容滚动发送文字</div>
<u-chat-box/>
<div style="margin-bottom: 15px"
>聊天内容框功能有发送emoji表情上传图片发送图片内容滚动发送文字</div
>
<u-chat-box />
</div>
</u-container-layout>
</template>
@ -11,6 +13,4 @@
import UChatBox from './components/u-chartBox/index.vue'
</script>
<style>
</style>
<style></style>

View File

@ -1,25 +1,25 @@
<template>
<u-container-layout>
<el-card style="margin-bottom: 20px">
<div style="margin-bottom: 10px">输入内容并点击复制按钮</div>
<el-input v-model="inputData" placeholder="请输入" style="width:400px;max-width:100%;" />
<el-button type="primary" @click="handleCopy(inputData,$event)">
<el-icon style="margin-right: 6px"><document-copy /></el-icon>
</el-button>
</el-card>
<el-card>
<div style="margin-bottom: 10px">复制成功后可在这粘贴测试</div>
<el-input v-model="testValue" placeholder="请输入" style="width:400px;max-width:100%;" />
</el-card>
</u-container-layout>
<u-container-layout>
<el-card style="margin-bottom: 20px">
<div style="margin-bottom: 10px">输入内容并点击复制按钮</div>
<el-input v-model="inputData" placeholder="请输入" style="width: 400px; max-width: 100%" />
<el-button type="primary" @click="handleCopy(inputData, $event)">
<el-icon style="margin-right: 6px"><document-copy /></el-icon>
</el-button>
</el-card>
<el-card>
<div style="margin-bottom: 10px">复制成功后可在这粘贴测试</div>
<el-input v-model="testValue" placeholder="请输入" style="width: 400px; max-width: 100%" />
</el-card>
</u-container-layout>
</template>
<script lang="ts" setup>
import {ref} from 'vue'
import clip from '@/utils/clipboard'
const inputData = ref('https://github.com/zouzhibin/vue-admin-perfect')
const testValue = ref('')
import { ref } from 'vue'
import clip from '@/utils/clipboard'
const inputData = ref('https://github.com/zouzhibin/vue-admin-perfect')
const testValue = ref('')
const handleCopy = (text, event)=> {
clip(text, event)
}
const handleCopy = (text, event) => {
clip(text, event)
}
</script>

View File

@ -4,44 +4,42 @@
<el-card class="box-card">
<template #header>
<div class="card-header">
<span>基础用法
</span>
<span>基础用法 </span>
</div>
</template>
<div>
<el-button class="item">Default</el-button>
<el-button type="primary" class="item">Primary</el-button>
<el-button type="success" class="item">Success</el-button>
<el-button type="info" class="item">Info</el-button>
<el-button type="warning" class="item">Warning</el-button>
<el-button type="danger" class="item">Danger</el-button>
<el-button class="item">中文</el-button>
<el-button plain class="item">Plain</el-button>
<el-button type="primary" plain class="item">Primary</el-button>
<el-button type="success" plain class="item">Success</el-button>
<el-button type="info" plain class="item">Info</el-button>
<el-button type="warning" plain class="item">Warning</el-button>
<el-button type="danger" plain class="item">Danger</el-button>
<el-button round class="item">Round</el-button>
<el-button type="primary" round class="item">Primary</el-button>
<el-button type="success" round class="item">Success</el-button>
<el-button type="info" round class="item">Info</el-button>
<el-button type="warning" round class="item">Warning</el-button>
<el-button type="danger" round class="item">Danger</el-button>
<el-button :icon="Search" circle class="item"/>
<el-button type="primary" :icon="Edit" circle class="item"/>
<el-button type="success" :icon="Check" circle class="item"/>
<el-button type="info" :icon="Message" circle class="item"/>
<el-button type="warning" :icon="Star" circle class="item"/>
<el-button type="danger" :icon="Delete" circle class="item"/>
<el-button type="primary" class="item">Primary</el-button>
<el-button type="success" class="item">Success</el-button>
<el-button type="info" class="item">Info</el-button>
<el-button type="warning" class="item">Warning</el-button>
<el-button type="danger" class="item">Danger</el-button>
<el-button class="item">中文</el-button>
<el-button plain class="item">Plain</el-button>
<el-button type="primary" plain class="item">Primary</el-button>
<el-button type="success" plain class="item">Success</el-button>
<el-button type="info" plain class="item">Info</el-button>
<el-button type="warning" plain class="item">Warning</el-button>
<el-button type="danger" plain class="item">Danger</el-button>
<el-button round class="item">Round</el-button>
<el-button type="primary" round class="item">Primary</el-button>
<el-button type="success" round class="item">Success</el-button>
<el-button type="info" round class="item">Info</el-button>
<el-button type="warning" round class="item">Warning</el-button>
<el-button type="danger" round class="item">Danger</el-button>
<el-button :icon="Search" circle class="item" />
<el-button type="primary" :icon="Edit" circle class="item" />
<el-button type="success" :icon="Check" circle class="item" />
<el-button type="info" :icon="Message" circle class="item" />
<el-button type="warning" :icon="Star" circle class="item" />
<el-button type="danger" :icon="Delete" circle class="item" />
</div>
</el-card>
<el-card class="box-card">
<template #header>
<div class="card-header">
<span>禁用状态
</span>
<span>禁用状态 </span>
</div>
</template>
<div>
@ -63,8 +61,7 @@
<el-card class="box-card">
<template #header>
<div class="card-header">
<span>文字按钮
</span>
<span>文字按钮 </span>
</div>
</template>
<div>
@ -76,14 +73,13 @@
<el-card class="box-card">
<template #header>
<div class="card-header">
<span>图标按钮
</span>
<span>图标按钮 </span>
</div>
</template>
<div>
<el-button type="primary" :icon="Edit" class="item"/>
<el-button type="primary" :icon="Share" class="item"/>
<el-button type="primary" :icon="Delete" class="item"/>
<el-button type="primary" :icon="Edit" class="item" />
<el-button type="primary" :icon="Share" class="item" />
<el-button type="primary" :icon="Delete" class="item" />
<el-button type="primary" :icon="Search" class="item">Search</el-button>
<el-button type="primary" class="item">
Upload<el-icon class="el-icon--right"><Upload /></el-icon>
@ -94,8 +90,7 @@
<el-card class="box-card">
<template #header>
<div class="card-header">
<span>按钮组
</span>
<span>按钮组 </span>
</div>
</template>
<div>
@ -103,17 +98,16 @@
<el-button type="primary" class="item">
下一页<el-icon class="el-icon--right"><ArrowRight /></el-icon>
</el-button>
<el-button type="primary" :icon="Edit" class="item"/>
<el-button type="primary" :icon="Share" class="item"/>
<el-button type="primary" :icon="Delete" class="item"/>
<el-button type="primary" :icon="Edit" class="item" />
<el-button type="primary" :icon="Share" class="item" />
<el-button type="primary" :icon="Delete" class="item" />
</div>
</el-card>
<el-card class="box-card">
<template #header>
<div class="card-header">
<span>加载中
</span>
<span>加载中 </span>
</div>
</template>
<div>
@ -124,8 +118,8 @@
<div class="custom-loading">
<svg class="circular" viewBox="-10, -10, 50, 50">
<path
class="path"
d="
class="path"
d="
M 30 15
L 28 17
M 25.61 25.61
@ -133,7 +127,7 @@
A 15 15, 0, 1, 1, 27.99 7.5
L 15 15
"
style="stroke-width: 4px; fill: rgba(0, 0, 0, 0)"
style="stroke-width: 4px; fill: rgba(0, 0, 0, 0)"
/>
</svg>
</div>
@ -146,52 +140,40 @@
<el-card class="box-card">
<template #header>
<div class="card-header">
<span>自定义颜色
</span>
<span>自定义颜色 </span>
</div>
</template>
<div>
<el-button color="#626aef" class="item">Default</el-button>
<el-button color="#626aef" plain class="item">Plain</el-button>
<el-button color="#626aef" class="item">Default</el-button>
<el-button color="#626aef" plain class="item">Plain</el-button>
<el-button color="#626aef" disabled class="item">Disabled</el-button>
<el-button color="#626aef" disabled plain class="item"
>Disabled Plain</el-button
>
<el-button color="#626aef" disabled class="item">Disabled</el-button>
<el-button color="#626aef" disabled plain class="item">Disabled Plain</el-button>
</div>
</el-card>
</div>
</u-container-layout>
</template>
<script lang="ts" setup>
import {
Check,
Delete,
Edit,
Message,
Search,
Share,
Star
} from '@element-plus/icons-vue'
import { Check, Delete, Edit, Message, Search, Share, Star } from '@element-plus/icons-vue'
</script>
<style>
.card-header {
display: flex;
justify-content: space-between;
align-items: center;
}
.card-header {
display: flex;
justify-content: space-between;
align-items: center;
}
.text {
font-size: 14px;
}
.text {
font-size: 14px;
}
.item {
margin-bottom: 18px;
}
.item {
margin-bottom: 18px;
}
.box-card {
width: 100%;
margin-bottom:20px;
}
.box-card {
width: 100%;
margin-bottom: 20px;
}
</style>

Some files were not shown because too many files have changed in this diff Show More