feat: 页面编写

master
xjs 2025-05-19 10:58:23 +08:00
parent 24220d8f27
commit 2254df4e95
51 changed files with 2844 additions and 375 deletions

View File

@ -4,9 +4,6 @@
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
<!-- WX JS SDK 微信小程序一定要引入这个文件 可以自己去官方下载最新的-->
<script type="text/javascript" src="/js/jweixin-1.6.0.js"></script>
<script type="text/javascript" src="/js/uni.webview.1.5.6.js" defer></script>
<title></title>
</head>
<body>

View File

@ -19,6 +19,7 @@
"crypto-js": "^4.2.0",
"echarts": "^5.6.0",
"echarts-gl": "^2.0.9",
"gsap": "^3.13.0",
"pinia": "^2.3.0",
"pinia-plugin-persistedstate": "^4.1.3",
"semver": "^7.6.3",
@ -30,6 +31,7 @@
},
"devDependencies": {
"@iconify-json/carbon": "^1.2.8",
"@types/gsap": "^3.0.0",
"@types/qs": "^6.9.17",
"@unocss/preset-wind": "^0.65.2",
"@vitejs/plugin-basic-ssl": "^1.2.0",

View File

@ -29,6 +29,9 @@ importers:
echarts-gl:
specifier: ^2.0.9
version: 2.0.9(echarts@5.6.0)
gsap:
specifier: ^3.13.0
version: 3.13.0
pinia:
specifier: ^2.3.0
version: 2.3.0(typescript@5.6.3)(vue@3.5.13(typescript@5.6.3))
@ -57,6 +60,9 @@ importers:
'@iconify-json/carbon':
specifier: ^1.2.8
version: 1.2.8
'@types/gsap':
specifier: ^3.0.0
version: 3.0.0
'@types/qs':
specifier: ^6.9.17
version: 6.9.17
@ -637,6 +643,10 @@ packages:
'@types/estree@1.0.6':
resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==}
'@types/gsap@3.0.0':
resolution: {integrity: sha512-BbWLi4WRHGze4C8NV7U7yRevuBFiPkPZZyGa0rryanvh/9HPUFXTNBXsGQxJZJq7Ix7j4RXMYodP3s+OsqCErg==}
deprecated: This is a stub types definition. gsap provides its own type definitions, so you do not need this installed.
'@types/node@22.10.1':
resolution: {integrity: sha512-qKgsUwfHZV2WCWLAnVP1JqnpE6Im6h3Y0+fYgMTasNQ7V++CBX5OT1as0g0f+OyubbFqhf6XVNIsmN4IIhEgGQ==}
@ -1321,6 +1331,9 @@ packages:
resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==}
engines: {node: '>= 0.4'}
gsap@3.13.0:
resolution: {integrity: sha512-QL7MJ2WMjm1PHWsoFrAQH/J8wUeqZvMtHO58qdekHpCfhvhSL4gSiz6vJf5EeMP0LOn3ZCprL2ki/gjED8ghVw==}
gzip-size@6.0.0:
resolution: {integrity: sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==}
engines: {node: '>=10'}
@ -3035,6 +3048,10 @@ snapshots:
'@types/estree@1.0.6': {}
'@types/gsap@3.0.0':
dependencies:
gsap: 3.13.0
'@types/node@22.10.1':
dependencies:
undici-types: 6.20.0
@ -3954,6 +3971,8 @@ snapshots:
gopd@1.2.0: {}
gsap@3.13.0: {}
gzip-size@6.0.0:
dependencies:
duplexer: 0.1.2

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="8.005532264709473" height="9.987500190734863" viewBox="0 0 8.005532264709473 9.987500190734863"><g><path d="M7.23431,5.99L6.02431,5.99C6.02431,5.98,6.02431,5.98,6.02431,5.97L6.02431,1C6.02431,0.45,5.57431,0,5.02431,0L2.99431,0C2.44431,0,1.99431,0.45,1.99431,1L1.99431,5.97C1.99431,5.98,1.99431,5.98,1.99431,5.99L0.77431,5.99C0.0843096,5.99,-0.25569,6.69,0.224309,7.09L3.45431,9.8C3.75431,10.05,4.24431,10.05,4.54431,9.8L7.77431,7.09C8.26431,6.69,7.92431,5.99,7.23431,5.99Z" fill="#FF4E4E" fill-opacity="1" style="mix-blend-mode:passthrough"/></g></svg>

After

Width:  |  Height:  |  Size: 668 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="8.005532785518852" height="9.987500608192311" viewBox="0 0 8.005532785518852 9.987500608192311"><g transform="matrix(-1,-5.2146120310681e-8,5.2146120310681e-8,-1,16.011064008609537,19.97500163384207)"><path d="M15.239842264709473,15.977500608192312L14.029842264709472,15.977500608192312C14.029842264709472,15.967500608192312,14.029842264709472,15.967500608192312,14.029842264709472,15.957500608192312L14.029842264709472,10.987500608192311C14.029842264709472,10.43750060819231,13.579842264709473,9.987500608192311,13.029842264709472,9.987500608192311L10.999842264709473,9.987500608192311C10.449842264709472,9.987500608192311,9.999842264709473,10.43750060819231,9.999842264709473,10.987500608192311L9.999842264709473,15.957500608192312C9.999842264709473,15.967500608192312,9.999842264709473,15.967500608192312,9.999842264709473,15.977500608192312L8.779842264709472,15.977500608192312C8.089841864709472,15.977500608192312,7.749842264709473,16.67750060819231,8.229841264709473,17.07750060819231L11.459842264709472,19.78750060819231C11.759842264709473,20.03750060819231,12.249842264709471,20.03750060819231,12.549842264709472,19.78750060819231L15.779842264709472,17.07750060819231C16.269842264709474,16.67750060819231,15.929842264709473,15.977500608192312,15.239842264709473,15.977500608192312Z" fill="#4AFFA2" fill-opacity="1" style="mix-blend-mode:passthrough"/></g></svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 86 KiB

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="14.13671875" height="17.787841796875" viewBox="0 0 14.13671875 17.787841796875"><defs><linearGradient x1="0.5" y1="0" x2="0.5" y2="1" id="master_svg0_110_5610"><stop offset="0%" stop-color="#FFFFFF" stop-opacity="1"/><stop offset="51.01040005683899%" stop-color="#97BBFF" stop-opacity="1"/><stop offset="52.34435796737671%" stop-color="#1168FF" stop-opacity="1"/><stop offset="100%" stop-color="#1185FF" stop-opacity="1"/></linearGradient><linearGradient x1="0.24648989737033844" y1="0" x2="0.3002182700303045" y2="0.8341024570154847" id="master_svg1_110_5613"><stop offset="0%" stop-color="#FFFFFF" stop-opacity="1"/><stop offset="100%" stop-color="#2D8CFF" stop-opacity="1"/></linearGradient><linearGradient x1="0.5" y1="0" x2="0.5" y2="1" id="master_svg2_110_5623"><stop offset="0%" stop-color="#66E0FF" stop-opacity="0"/><stop offset="100%" stop-color="#1164FF" stop-opacity="0.5"/></linearGradient></defs><g><g style="opacity:0.30000001192092896;"><path d="M0.5,2.60546875L13.1633,10.46999875L0.5,17.78786875L0.5,15.87376875L5.18962,10.46999875L0.5,4.66468875L0.5,2.60546875Z" fill-rule="evenodd" fill="#044BB8" fill-opacity="1" style="mix-blend-mode:passthrough"/></g><g><path d="M0.5,0.8990478515625L13.1633,8.7635778515625L0.5,16.0814478515625L0.5,14.1673478515625L5.18962,8.7635778515625L0.5,2.9582678515625L0.5,0.8990478515625Z" fill-rule="evenodd" fill="url(#master_svg0_110_5610)" fill-opacity="1" style="mix-blend-mode:passthrough"/></g><g><path d="M0,0L0,2.95833L0,3.13506L4.53757,8.75214L0,13.9807L0,16.948L14.1359,8.77909L0,0ZM1,2.78161L5.84168,8.77514L1,14.3541L1,15.2151L12.1907,8.74819L1,1.79821L1,2.78161Z" fill-rule="evenodd" fill="url(#master_svg1_110_5613)" fill-opacity="1" style="mix-blend-mode:passthrough"/></g><g><path d="M0.5,0.89892578125L13.1633,8.76345578125L5.18962,8.76345578125L0.5,2.95814578125L0.5,0.89892578125Z" fill-rule="evenodd" fill="url(#master_svg2_110_5623)" fill-opacity="1" style="mix-blend-mode:passthrough"/></g></g></svg>

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 6.7 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 5.5 KiB

View File

@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1"><defs><linearGradient x1="0.5" y1="0" x2="0.5" y2="1" id="master_svg0_95_7905"><stop offset="0%" stop-color="#23518C" stop-opacity="0.20000000298023224"/><stop offset="100%" stop-color="#17439D" stop-opacity="0.10000000149011612"/></linearGradient><radialGradient cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" id="master_svg1_95_7906" gradientTransform="translate(272.25 210.25) rotate(90) scale(33.016276359558105 293.6848504078262)"><stop offset="0%" stop-color="#2773FF" stop-opacity="0.10000000149011612"/><stop offset="100%" stop-color="#2773FF" stop-opacity="0"/></radialGradient><radialGradient cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" id="master_svg2_95_7907" gradientTransform="translate(272.25 210.25) rotate(90) scale(7.3813605308532715 170.33950726831247)"><stop offset="0%" stop-color="#2773FF" stop-opacity="0.20000000298023224"/><stop offset="100%" stop-color="#2773FF" stop-opacity="0"/></radialGradient><radialGradient cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" id="master_svg3_95_7908" gradientTransform="translate(272.25 210.25) rotate(90) scale(3.5998570919036865 121.80235547062695)"><stop offset="0%" stop-color="#2773FF" stop-opacity="0.5"/><stop offset="100%" stop-color="#2773FF" stop-opacity="0"/></radialGradient><linearGradient x1="0.5" y1="0.05106060206890106" x2="0.5" y2="1" id="master_svg4_81_5443"><stop offset="0%" stop-color="#525DFF" stop-opacity="0"/><stop offset="100%" stop-color="#525DFF" stop-opacity="0.47999998927116394"/></linearGradient><radialGradient cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" id="master_svg5_13_2169" gradientTransform="translate(248.49790859222412 1.25) rotate(0) scale(5.699835777282715 Infinity)"><stop offset="0%" stop-color="#4FE4FF" stop-opacity="1"/><stop offset="100%" stop-color="#2773FF" stop-opacity="0"/></radialGradient><linearGradient x1="1" y1="0.5" x2="0" y2="0.5" id="master_svg6_13_2170"><stop offset="0%" stop-color="#36C8FF" stop-opacity="0"/><stop offset="53.635478019714355%" stop-color="#27AEFF" stop-opacity="1"/><stop offset="100%" stop-color="#1997FF" stop-opacity="0.20000000298023224"/></linearGradient></defs><g><g><path d="M0.25,0.25L544.25,0.25L544.25,210.25L0.25,210.25L0.25,0.25Z" fill-rule="evenodd" fill="#000000" fill-opacity="0.25"/><path d="M0.25,0.25L544.25,0.25L544.25,210.25L0.25,210.25L0.25,0.25Z" fill-rule="evenodd" fill="url(#master_svg0_95_7905)" fill-opacity="1"/><path d="M0.25,0.25L544.25,0.25L544.25,210.25L0.25,210.25L0.25,0.25Z" fill-rule="evenodd" fill="url(#master_svg1_95_7906)" fill-opacity="1"/><path d="M0.25,0.25L544.25,0.25L544.25,210.25L0.25,210.25L0.25,0.25Z" fill-rule="evenodd" fill="url(#master_svg2_95_7907)" fill-opacity="1"/><path d="M0.25,0.25L544.25,0.25L544.25,210.25L0.25,210.25L0.25,0.25Z" fill-rule="evenodd" fill="url(#master_svg3_95_7908)" fill-opacity="1"/><path d="M544.5,0L0,0L0,210.5L544.5,210.5L544.5,0ZM0.5,210L0.5,0.5L544,0.5L544,210L0.5,210Z" fill-rule="evenodd" fill="url(#master_svg4_81_5443)" fill-opacity="1"/></g><g style="opacity:0.44999998807907104;"><path d="M478.25,1.75L287.725,1.75L243.498,1.75L62.25,1.75L62.25,0.75L243.498,0.75L287.725,0.75L478.25,0.75L478.25,1.75Z" fill-rule="evenodd" fill="url(#master_svg5_13_2169)" fill-opacity="1"/><path d="M478.25,1.75L287.725,1.75L243.498,1.75L62.25,1.75L62.25,0.75L243.498,0.75L287.725,0.75L478.25,0.75L478.25,1.75Z" fill-rule="evenodd" fill="url(#master_svg6_13_2170)" fill-opacity="1"/></g></g></svg>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" viewBox="0 0 544.5 210.75"><defs><linearGradient x1="0.5" y1="0" x2="0.5" y2="1" id="master_svg0_95_7905"><stop offset="0%" stop-color="#23518C" stop-opacity="0.20000000298023224"/><stop offset="100%" stop-color="#17439D" stop-opacity="0.10000000149011612"/></linearGradient><radialGradient cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" id="master_svg1_95_7906" gradientTransform="translate(272.25 210.5) rotate(90) scale(33.016276359558105 293.6848504078262)"><stop offset="0%" stop-color="#2773FF" stop-opacity="0.10000000149011612"/><stop offset="100%" stop-color="#2773FF" stop-opacity="0"/></radialGradient><radialGradient cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" id="master_svg2_95_7907" gradientTransform="translate(272.25 210.5) rotate(90) scale(7.3813605308532715 170.33950726831247)"><stop offset="0%" stop-color="#2773FF" stop-opacity="0.20000000298023224"/><stop offset="100%" stop-color="#2773FF" stop-opacity="0"/></radialGradient><radialGradient cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" id="master_svg3_95_7908" gradientTransform="translate(272.25 210.5) rotate(90) scale(3.5998570919036865 121.80235547062695)"><stop offset="0%" stop-color="#2773FF" stop-opacity="0.5"/><stop offset="100%" stop-color="#2773FF" stop-opacity="0"/></radialGradient><linearGradient x1="0.5" y1="0.05106060206890106" x2="0.5" y2="1" id="master_svg4_81_5443"><stop offset="0%" stop-color="#525DFF" stop-opacity="0"/><stop offset="100%" stop-color="#525DFF" stop-opacity="0.47999998927116394"/></linearGradient><radialGradient cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" id="master_svg5_13_2169" gradientTransform="translate(250.49790859222412 0.5) rotate(0) scale(5.699835777282715 Infinity)"><stop offset="0%" stop-color="#4FE4FF" stop-opacity="1"/><stop offset="100%" stop-color="#2773FF" stop-opacity="0"/></radialGradient><linearGradient x1="1" y1="0.5" x2="0" y2="0.5" id="master_svg6_13_2170"><stop offset="0%" stop-color="#36C8FF" stop-opacity="0"/><stop offset="53.635478019714355%" stop-color="#27AEFF" stop-opacity="1"/><stop offset="100%" stop-color="#1997FF" stop-opacity="0.20000000298023224"/></linearGradient></defs><g><g><path d="M0.25 0.5C0.25 0.5 0.25 0.5 0.25 0.5L544.25 0.5C544.25 0.5 544.25 0.5 544.25 0.5L544.25 210.5C544.25 210.5 544.25 210.5 544.25 210.5L0.25 210.5C0.25 210.5 0.25 210.5 0.25 210.5Z" fill="#000000" fill-opacity="0.25"/><path d="M0.25 0.5C0.25 0.5 0.25 0.5 0.25 0.5L544.25 0.5C544.25 0.5 544.25 0.5 544.25 0.5L544.25 210.5C544.25 210.5 544.25 210.5 544.25 210.5L0.25 210.5C0.25 210.5 0.25 210.5 0.25 210.5Z" fill="url(#master_svg0_95_7905)" fill-opacity="1"/><path d="M0.25 0.5C0.25 0.5 0.25 0.5 0.25 0.5L544.25 0.5C544.25 0.5 544.25 0.5 544.25 0.5L544.25 210.5C544.25 210.5 544.25 210.5 544.25 210.5L0.25 210.5C0.25 210.5 0.25 210.5 0.25 210.5Z" fill="url(#master_svg1_95_7906)" fill-opacity="1"/><path d="M0.25 0.5C0.25 0.5 0.25 0.5 0.25 0.5L544.25 0.5C544.25 0.5 544.25 0.5 544.25 0.5L544.25 210.5C544.25 210.5 544.25 210.5 544.25 210.5L0.25 210.5C0.25 210.5 0.25 210.5 0.25 210.5Z" fill="url(#master_svg2_95_7907)" fill-opacity="1"/><path d="M0.25 0.5C0.25 0.5 0.25 0.5 0.25 0.5L544.25 0.5C544.25 0.5 544.25 0.5 544.25 0.5L544.25 210.5C544.25 210.5 544.25 210.5 544.25 210.5L0.25 210.5C0.25 210.5 0.25 210.5 0.25 210.5Z" fill="url(#master_svg3_95_7908)" fill-opacity="1"/><path d="M0.25 0.5C0.25 0.5 0.25 0.5 0.25 0.5L544.25 0.5C544.25 0.5 544.25 0.5 544.25 0.5L544.25 210.5C544.25 210.5 544.25 210.5 544.25 210.5L0.25 210.5C0.25 210.5 0.25 210.5 0.25 210.5Z" stroke="url(#master_svg4_81_5443)" fill-opacity="0" fill="none" stroke-width="0.5"/></g><g style="opacity:0.44999998807907104;"><path d="M480.25,1L289.725,1L245.498,1L64.25,1L64.25,0L245.498,0L289.725,0L480.25,0L480.25,1Z" fill-rule="evenodd" fill="url(#master_svg5_13_2169)" fill-opacity="1"/><path d="M480.25,1L289.725,1L245.498,1L64.25,1L64.25,0L245.498,0L289.725,0L480.25,0L480.25,1Z" fill-rule="evenodd" fill="url(#master_svg6_13_2170)" fill-opacity="1"/></g></g></svg>

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 4.0 KiB

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" viewBox="0 0 188 36"><defs><linearGradient x1="1" y1="0.5" x2="0" y2="0.5" id="master_svg0_110_5669"><stop offset="0%" stop-color="#2773FF" stop-opacity="0.4000000059604645"/><stop offset="23.317307233810425%" stop-color="#2773FF" stop-opacity="0.25"/><stop offset="100%" stop-color="#2773FF" stop-opacity="0.05999999865889549"/></linearGradient><radialGradient cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" id="master_svg1_110_4138" gradientTransform="translate(132.2986946851015 34.756103515625) rotate(76.51046439419082) scale(17.356884100084887 29.26667369717238)"><stop offset="0%" stop-color="#4FE4FF" stop-opacity="1"/><stop offset="100%" stop-color="#2773FF" stop-opacity="0"/></radialGradient><linearGradient x1="1" y1="0.5" x2="0" y2="0.5" id="master_svg2_110_4139"><stop offset="0%" stop-color="#36C8FF" stop-opacity="0"/><stop offset="53.635478019714355%" stop-color="#27AEFF" stop-opacity="1"/><stop offset="100%" stop-color="#1997FF" stop-opacity="0.20000000298023224"/></linearGradient><linearGradient x1="1" y1="0.5" x2="0" y2="0.5" id="master_svg3_110_5664"><stop offset="0%" stop-color="#2773FF" stop-opacity="0"/><stop offset="81.4047634601593%" stop-color="#2773FF" stop-opacity="0.21617308259010315"/><stop offset="100%" stop-color="#2773FF" stop-opacity="0.30000001192092896"/></linearGradient><linearGradient x1="1" y1="0.5" x2="0" y2="0.5" id="master_svg4_110_5643"><stop offset="0%" stop-color="#2773FF" stop-opacity="0.30000001192092896"/><stop offset="18.59523504972458%" stop-color="#2773FF" stop-opacity="0.21617308259010315"/><stop offset="100%" stop-color="#2773FF" stop-opacity="0"/></linearGradient><linearGradient x1="1" y1="0.5" x2="0" y2="0.5" id="master_svg5_110_5664"><stop offset="0%" stop-color="#2773FF" stop-opacity="0"/><stop offset="81.4047634601593%" stop-color="#2773FF" stop-opacity="0.21617308259010315"/><stop offset="100%" stop-color="#2773FF" stop-opacity="0.30000001192092896"/></linearGradient></defs><g><g><path d="M0,1L177.338,1L138.238,30.561L0,30.561L0,1Z" fill-rule="evenodd" fill="url(#master_svg0_110_5669)" fill-opacity="1"/></g><g><path d="M183.644,1.5L295.5,1.5L295.5,0.5L183.306,0.5L139.079,34.2561L0,34.2561L0,35.2561L139.417,35.2561L183.644,1.5Z" fill-rule="evenodd" fill="url(#master_svg1_110_4138)" fill-opacity="1"/><path d="M183.644,1.5L295.5,1.5L295.5,0.5L183.306,0.5L139.079,34.2561L0,34.2561L0,35.2561L139.417,35.2561L183.644,1.5Z" fill-rule="evenodd" fill="url(#master_svg2_110_4139)" fill-opacity="1"/></g><g><g><path d="M182.97852,1L294.145,1L288.074,6.2439L176,6.2439L182.97852,1Z" fill-rule="evenodd" fill="url(#master_svg3_110_5664)" fill-opacity="1"/></g><g><path d="M182.999984375,1L263.919784375,1L251.97318437500002,11.4878L169.146484375,11.4878L182.999984375,1Z" fill-rule="evenodd" fill="url(#master_svg4_110_5643)" fill-opacity="1"/></g><g style="opacity:0.5;"><g><path d="M184.1035,1L295.464,1L295.464,23.0244L155,23.0244L184.1035,1Z" fill-rule="evenodd" fill="url(#master_svg5_110_5664)" fill-opacity="1"/></g></g></g></g></svg>

After

Width:  |  Height:  |  Size: 3.1 KiB

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" viewBox="0 0 255 36"><defs><linearGradient x1="1" y1="0.5" x2="0" y2="0.5" id="master_svg0_110_5669"><stop offset="0%" stop-color="#2773FF" stop-opacity="0.4000000059604645"/><stop offset="23.317307233810425%" stop-color="#2773FF" stop-opacity="0.25"/><stop offset="100%" stop-color="#2773FF" stop-opacity="0.05999999865889549"/></linearGradient><radialGradient cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" id="master_svg1_110_4537" gradientTransform="translate(114.16638627648354 34.756103515625) rotate(78.3045141357308) scale(17.2358897800393 25.079449849220687)"><stop offset="0%" stop-color="#4FE4FF" stop-opacity="1"/><stop offset="100%" stop-color="#2773FF" stop-opacity="0"/></radialGradient><linearGradient x1="1.578010082244873" y1="0.6616930961608887" x2="-0.00028524507193582627" y2="0.6588591327853952" id="master_svg2_110_4538"><stop offset="0%" stop-color="#36C8FF" stop-opacity="0"/><stop offset="53.635478019714355%" stop-color="#27AEFF" stop-opacity="1"/><stop offset="100%" stop-color="#1997FF" stop-opacity="0.20000000298023224"/></linearGradient><radialGradient cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" id="master_svg3_110_5566" gradientTransform="translate(538.6601538022733 1) rotate(0) scale(9.584570288854593 Infinity)"><stop offset="0%" stop-color="#4FE4FF" stop-opacity="1"/><stop offset="100%" stop-color="#2773FF" stop-opacity="0"/></radialGradient><linearGradient x1="1" y1="0.5" x2="0" y2="0.5" id="master_svg4_110_5567"><stop offset="0%" stop-color="#1997FF" stop-opacity="0.20000000298023224"/><stop offset="100%" stop-color="#27AEFF" stop-opacity="1"/></linearGradient><linearGradient x1="1" y1="0.5" x2="0" y2="0.5" id="master_svg5_110_5664"><stop offset="0%" stop-color="#2773FF" stop-opacity="0"/><stop offset="81.4047634601593%" stop-color="#2773FF" stop-opacity="0.21617308259010315"/><stop offset="100%" stop-color="#2773FF" stop-opacity="0.30000001192092896"/></linearGradient><linearGradient x1="1" y1="0.5" x2="0" y2="0.5" id="master_svg6_110_5643"><stop offset="0%" stop-color="#2773FF" stop-opacity="0.30000001192092896"/><stop offset="18.59523504972458%" stop-color="#2773FF" stop-opacity="0.21617308259010315"/><stop offset="100%" stop-color="#2773FF" stop-opacity="0"/></linearGradient><linearGradient x1="1" y1="0.5" x2="0.06541949510574341" y2="0.5" id="master_svg7_110_5455"><stop offset="0%" stop-color="#2773FF" stop-opacity="0"/><stop offset="81.4047634601593%" stop-color="#2773FF" stop-opacity="0.21617308259010315"/><stop offset="100%" stop-color="#2773FF" stop-opacity="0.30000001192092896"/></linearGradient></defs><g><g><g><path d="M0,1L217.337,1L178.239,30.561L0,30.561L0,1Z" fill-rule="evenodd" fill="url(#master_svg0_110_5669)" fill-opacity="1"/></g><g><path d="M225.643,1.5L255,1.5L255,0.5L225.305,0.5L181.079,34.2561L0,34.2561L0,35.2561L181.417,35.2561L225.643,1.5Z" fill-rule="evenodd" fill="url(#master_svg1_110_4537)" fill-opacity="1"/><path d="M225.643,1.5L255,1.5L255,0.5L225.305,0.5L181.079,34.2561L0,34.2561L0,35.2561L181.417,35.2561L225.643,1.5Z" fill-rule="evenodd" fill="url(#master_svg2_110_4538)" fill-opacity="1"/></g></g><g><g><path d="M925.000609375,1.5L225.474609375,1.5L225.474609375,0.5L925.000609375,0.5L925.000609375,1.5Z" fill-rule="evenodd" fill="url(#master_svg3_110_5566)" fill-opacity="1"/><path d="M925.000609375,1.5L225.474609375,1.5L225.474609375,0.5L925.000609375,0.5L925.000609375,1.5Z" fill-rule="evenodd" fill="url(#master_svg4_110_5567)" fill-opacity="1"/></g><g><path d="M225.97852,1L924.145,1L918.074,6.2439L219,6.2439L225.97852,1Z" fill-rule="evenodd" fill="url(#master_svg5_110_5664)" fill-opacity="1"/></g><g><path d="M225.3535,1L893.92,1L881.973,11.4878L211.5,11.4878L225.3535,1Z" fill-rule="evenodd" fill="url(#master_svg6_110_5643)" fill-opacity="1"/></g><g><path d="M225.1035,0L924.964,0L924.964,22.0244L197,22.0244L225.1035,0Z" fill-rule="evenodd" fill="url(#master_svg7_110_5455)" fill-opacity="1"/></g></g></g></svg>

After

Width:  |  Height:  |  Size: 4.0 KiB

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" viewBox="188 0 108 36"><defs><radialGradient cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" id="master_svg0_110_4138" gradientTransform="translate(132.2986946851015 34.756103515625) rotate(76.51046439419082) scale(17.356884100084887 29.26667369717238)"><stop offset="0%" stop-color="#4FE4FF" stop-opacity="1"/><stop offset="100%" stop-color="#2773FF" stop-opacity="0"/></radialGradient><linearGradient x1="1" y1="0.5" x2="0" y2="0.5" id="master_svg1_110_4139"><stop offset="0%" stop-color="#36C8FF" stop-opacity="0"/><stop offset="53.635478019714355%" stop-color="#27AEFF" stop-opacity="1"/><stop offset="100%" stop-color="#1997FF" stop-opacity="0.20000000298023224"/></linearGradient><linearGradient x1="1" y1="0.5" x2="0" y2="0.5" id="master_svg2_110_5664"><stop offset="0%" stop-color="#2773FF" stop-opacity="0"/><stop offset="81.4047634601593%" stop-color="#2773FF" stop-opacity="0.21617308259010315"/><stop offset="100%" stop-color="#2773FF" stop-opacity="0.30000001192092896"/></linearGradient><linearGradient x1="1" y1="0.5" x2="0" y2="0.5" id="master_svg3_110_5643"><stop offset="0%" stop-color="#2773FF" stop-opacity="0.30000001192092896"/><stop offset="18.59523504972458%" stop-color="#2773FF" stop-opacity="0.21617308259010315"/><stop offset="100%" stop-color="#2773FF" stop-opacity="0"/></linearGradient><linearGradient x1="1" y1="0.5" x2="0" y2="0.5" id="master_svg4_110_5664"><stop offset="0%" stop-color="#2773FF" stop-opacity="0"/><stop offset="81.4047634601593%" stop-color="#2773FF" stop-opacity="0.21617308259010315"/><stop offset="100%" stop-color="#2773FF" stop-opacity="0.30000001192092896"/></linearGradient><linearGradient x1="0.9886833429336548" y1="0.5" x2="0" y2="0.5" id="master_svg5_110_5647"><stop offset="0%" stop-color="#02DBFF" stop-opacity="0"/><stop offset="100%" stop-color="#01B5FF" stop-opacity="1"/></linearGradient></defs><g><g><path d="M183.644,1.5L295.5,1.5L295.5,0.5L183.306,0.5L139.079,34.2561L0,34.2561L0,35.2561L139.417,35.2561L183.644,1.5Z" fill-rule="evenodd" fill="url(#master_svg0_110_4138)" fill-opacity="1"/><path d="M183.644,1.5L295.5,1.5L295.5,0.5L183.306,0.5L139.079,34.2561L0,34.2561L0,35.2561L139.417,35.2561L183.644,1.5Z" fill-rule="evenodd" fill="url(#master_svg1_110_4139)" fill-opacity="1"/></g><g><g><path d="M182.97852,1L294.145,1L288.074,6.2439L176,6.2439L182.97852,1Z" fill-rule="evenodd" fill="url(#master_svg2_110_5664)" fill-opacity="1"/></g><g><path d="M182.999984375,1L263.919784375,1L251.97318437500002,11.4878L169.146484375,11.4878L182.999984375,1Z" fill-rule="evenodd" fill="url(#master_svg3_110_5643)" fill-opacity="1"/></g><g style="opacity:0.5;"><g><path d="M184.1035,1L295.464,1L295.464,23.0244L155,23.0244L184.1035,1Z" fill-rule="evenodd" fill="url(#master_svg4_110_5664)" fill-opacity="1"/></g><g><g><path d="M268.89489541992185,5.195068359375L263.72240541992187,10.438968359375L260.8193054199219,10.438968359375L265.9917854199219,5.195068359375L268.89489541992185,5.195068359375ZM274.9515054199219,5.195068359375L269.78065541992186,10.438968359375L266.8759454199219,10.438968359375L272.0493054199219,5.195068359375L274.9515054199219,5.195068359375ZM281.00820541992186,5.195068359375L275.83480541992185,10.438968359375L272.93260541992186,10.438968359375L278.10600541992187,5.195068359375L281.00820541992186,5.195068359375ZM287.06480541992187,5.195068359375L281.89140541992185,10.438968359375L278.98920541992186,10.438968359375L284.1601054199219,5.195068359375L287.06480541992187,5.195068359375ZM286.9392054199219,10.438968359375L292.11170541992186,5.195068359375L289.20860541992187,5.195068359375L284.03610541992185,10.438968359375L286.9392054199219,10.438968359375Z" fill-rule="evenodd" fill="url(#master_svg5_110_5647)" fill-opacity="1"/></g></g></g></g></g></svg>

After

Width:  |  Height:  |  Size: 3.8 KiB

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" viewBox="256 0 669 36"><defs><radialGradient cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" id="master_svg0_110_5566" gradientTransform="translate(538.6601538022733 1) rotate(0) scale(9.584570288854593 Infinity)"><stop offset="0%" stop-color="#4FE4FF" stop-opacity="1"/><stop offset="100%" stop-color="#2773FF" stop-opacity="0"/></radialGradient><linearGradient x1="1" y1="0.5" x2="0" y2="0.5" id="master_svg1_110_5567"><stop offset="0%" stop-color="#1997FF" stop-opacity="0.20000000298023224"/><stop offset="100%" stop-color="#27AEFF" stop-opacity="1"/></linearGradient><linearGradient x1="1" y1="0.5" x2="0" y2="0.5" id="master_svg2_110_5664"><stop offset="0%" stop-color="#2773FF" stop-opacity="0"/><stop offset="81.4047634601593%" stop-color="#2773FF" stop-opacity="0.21617308259010315"/><stop offset="100%" stop-color="#2773FF" stop-opacity="0.30000001192092896"/></linearGradient><linearGradient x1="1" y1="0.5" x2="0" y2="0.5" id="master_svg3_110_5643"><stop offset="0%" stop-color="#2773FF" stop-opacity="0.30000001192092896"/><stop offset="18.59523504972458%" stop-color="#2773FF" stop-opacity="0.21617308259010315"/><stop offset="100%" stop-color="#2773FF" stop-opacity="0"/></linearGradient><linearGradient x1="1" y1="0.5" x2="0.06541949510574341" y2="0.5" id="master_svg4_110_5455"><stop offset="0%" stop-color="#2773FF" stop-opacity="0"/><stop offset="81.4047634601593%" stop-color="#2773FF" stop-opacity="0.21617308259010315"/><stop offset="100%" stop-color="#2773FF" stop-opacity="0.30000001192092896"/></linearGradient><linearGradient x1="0.9886833429336548" y1="0.5" x2="0" y2="0.5" id="master_svg5_110_5647"><stop offset="0%" stop-color="#02DBFF" stop-opacity="0"/><stop offset="100%" stop-color="#01B5FF" stop-opacity="1"/></linearGradient></defs><g><g><g><path d="M925.000609375,1.5L225.474609375,1.5L225.474609375,0.5L925.000609375,0.5L925.000609375,1.5Z" fill-rule="evenodd" fill="url(#master_svg0_110_5566)" fill-opacity="1"/><path d="M925.000609375,1.5L225.474609375,1.5L225.474609375,0.5L925.000609375,0.5L925.000609375,1.5Z" fill-rule="evenodd" fill="url(#master_svg1_110_5567)" fill-opacity="1"/></g><g><path d="M225.97852,1L924.145,1L918.074,6.2439L219,6.2439L225.97852,1Z" fill-rule="evenodd" fill="url(#master_svg2_110_5664)" fill-opacity="1"/></g><g><path d="M225.3535,1L893.92,1L881.973,11.4878L211.5,11.4878L225.3535,1Z" fill-rule="evenodd" fill="url(#master_svg3_110_5643)" fill-opacity="1"/></g><g><path d="M225.1035,0L924.964,0L924.964,22.0244L197,22.0244L225.1035,0Z" fill-rule="evenodd" fill="url(#master_svg4_110_5455)" fill-opacity="1"/></g><g><path d="M898.3959025,4.195068359375L893.2234125,9.438968359375L890.3203125,9.438968359375L895.4927925,4.195068359375L898.3959025,4.195068359375ZM904.4525125,4.195068359375L899.2816625,9.438968359375L896.3769525,9.438968359375L901.5503125,4.195068359375L904.4525125,4.195068359375ZM910.5092125,4.195068359375L905.3358125,9.438968359375L902.4336125,9.438968359375L907.6070125,4.195068359375L910.5092125,4.195068359375ZM916.5658125,4.195068359375L911.3924125,9.438968359375L908.4902125,9.438968359375L913.6611125,4.195068359375L916.5658125,4.195068359375ZM916.4402125,9.438968359375L921.6127125,4.195068359375L918.7096125,4.195068359375L913.5371125,9.438968359375L916.4402125,9.438968359375Z" fill-rule="evenodd" fill="url(#master_svg5_110_5647)" fill-opacity="1"/></g></g></g></svg>

After

Width:  |  Height:  |  Size: 3.4 KiB

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" viewBox="0 0 14 22"><defs><pattern x="1.9090908765792847" y="3" width="10.181818008422852" height="16" patternUnits="userSpaceOnUse" id="master_svg0_120_993"><image x="0" y="0" width="42" height="66" transform="scale(0.2424242382957822,0.24242424242424243)" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACoAAABCCAYAAAAhZERsAAAAAXNSR0IArs4c6QAAAARzQklUCAgICHwIZIgAAAOFSURBVGiB7dk/bBN3FMDx77vYlH9qJFKwQQIkaLsUIXXoAgssDIEyVIz8ERJ0AaXAUrUm7YnYAfEnXZspVZmqDqUIZgSICYQU/qwUKSj2ORJDqColuPcYEreWdbbPd7/f7xbedu89nT96z3e+k+F9OI6JGV2VtQHA69Uw/wGDF6r6hQtMt+gJ9TdIzfP4tFLVvS5AqWOspr9lie050f8ahREVprLCxoaWChIgnFXhVhbY2FCA8wX5A+H3LLB9QQEaOUaAOdfYvqH+kMx7yjFgpUts31CA7zfKXVV+Ala7wiaCAgz+TQl4hiNsYujIJ7IQCoeBRRxgE0MBfijINPDj8qFVbCooQKPAZYUHy4fWsGLiJBcD3favMg2sXU79I8qB0ka5Y+L8YGCiAN8V5IXA2ZaU8ckamWgzyjW9CXzZkjI2WSMTbUYDTgBzLSljkzUK9YtSV+HrtrQRrFEowGhBbgBTbenUWONQgPwA3wAv29KpsFag366XN4QcA8K2UmKsFSjA+U1yT4VrEaVEWGtQgMF5RoGnEaW+sUbvo1FRCXSnKg+BFRHl2PdZqxMFKBXkCcpoh3LsyVqHAjSKXFXhfodyLKwTqC8SsvT68qZDS0+sEyjAaFH+EjjTpaUr1vrF1B6Vmv6pcLBLS+QF5myizXgLJ4F6l5bIyTqH+kWpK4z3aFutwk1/Rtc1E86hV2q6RuB0j7ZQhFP+ZnndTDiHLsI14OMuLaEIx0sF+bU16fRiGqvqsAi3u7REIsEhdPyVDoU5ngHFDi0dkeBw9ZrnZxIiwRG0HOgRVQ51KPdEgoPVX5rVLQ2PJ8BgRDkWEixPVFWl4fELKZFgGVoOOANE/Xb3hQSLq79Q1c884RGwsq3UNxIsTXRSNe/BdQwhwRJ0LsBH+LwtnRgJFlZfDnQXyj1goCWdCgmGoVdqumYBpoHtLenUSDC8+gWYwAISDE60UtX9KtxqSRlDgiGoP6sf5Tye8v9vuVEkGFp9XpjEIhIMQCuBHlXhq+VDK0hIufryrG5l6YHjQywiIcVEVVVYeuCwjoQU0PE654A9OEBCwtVXarpD4RGQd4GEJH+DP9cVuvTA4QwJCaADQ/jATpfIvmM80N3lmi5WAj3q+rNjf0f9uq7NhTwWoZzFJHNxG/MhV8kIGTvGqjpcDvRI1o6u4c/ourFA92Xt6BmXXmvUq+776BTvAA46hzw7ExF1AAAAAElFTkSuQmCC"/></pattern></defs><g><g><rect x="1.9090908765792847" y="3" width="10.181818008422852" height="16" rx="0" fill="url(#master_svg0_120_993)" fill-opacity="1"/></g></g></svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 25 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 25 KiB

View File

@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" viewBox="0 0 127 130.5"><defs><radialGradient cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" id="master_svg0_85_02406" gradientTransform="translate(62.63833460211754 260.6206922531128) rotate(90) scale(129.7585763875395 128.02340110725947)"><stop offset="0%" stop-color="#4EAAFF" stop-opacity="1"/><stop offset="36.93000078201294%" stop-color="#0066FF" stop-opacity="0.5"/><stop offset="100%" stop-color="#000000" stop-opacity="0"/></radialGradient></defs><g><g transform="matrix(1,0,0,-1,0,261)" style="opacity:0.10000000149011612;"><path d="M63.5,130.5C28.4311,130.5,0,188.7103,0,260.5C0,260.5,127,260.5,127,260.5C127,188.6801,98.5743,130.5,63.5,130.5C63.5,130.5,63.5,130.5,63.5,130.5Z" fill="url(#master_svg0_85_02406)" fill-opacity="1"/></g><g style="opacity:0.20000000298023224;"><path d="M127,102L1,102L1,101L127,101L127,102Z" fill-rule="evenodd" fill="#0867A2" fill-opacity="1"/></g><g><path d="M126,1L0,1L0,0L126,0L126,1Z" fill-rule="evenodd" fill="#0867A2" fill-opacity="1"/></g><g><path d="M12,1L0,1L0,0L12,0L12,1Z" fill-rule="evenodd" fill="#00AAFF" fill-opacity="1"/></g></g></svg>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="127" height="104" viewBox="0 0 127 104"><defs><radialGradient cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" id="master_svg0_85_02406" gradientTransform="translate(62.63833460211754 261.1206922531128) rotate(90) scale(129.7585763875395 128.02340110725947)"><stop offset="0%" stop-color="#4EAAFF" stop-opacity="1"/><stop offset="36.93000078201294%" stop-color="#0066FF" stop-opacity="0.5"/><stop offset="100%" stop-color="#000000" stop-opacity="0"/></radialGradient></defs><g><g transform="matrix(1,0,0,-1,0,262)" style="opacity:0.10000000149011612;"><path d="M63.5,131C28.4311,131,0,189.2103,0,261C0,261,127,261,127,261C127,189.1801,98.5743,131,63.5,131C63.5,131,63.5,131,63.5,131Z" fill="url(#master_svg0_85_02406)" fill-opacity="1"/></g><g style="opacity:0.20000000298023224;"><path d="M127,102.5L1,102.5L1,101.5L127,101.5L127,102.5Z" fill-rule="evenodd" fill="#0867A2" fill-opacity="1"/></g><g><path d="M126,1.5L0,1.5L0,0.5L126,0.5L126,1.5Z" fill-rule="evenodd" fill="#0867A2" fill-opacity="1"/></g><g><path d="M12,1.5L0,1.5L0,0.5L12,0.5L12,1.5Z" fill-rule="evenodd" fill="#00AAFF" fill-opacity="1"/></g></g></svg>

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" viewBox="0 0 55 121"><defs><linearGradient x1="0.5" y1="0" x2="0.5" y2="1" id="master_svg0_85_7578"><stop offset="0%" stop-color="#0085FF" stop-opacity="0.5"/><stop offset="100%" stop-color="#0047FF" stop-opacity="0"/></linearGradient><linearGradient x1="0.49977484345436096" y1="0.9948660731315613" x2="0.49977484345436096" y2="0.000026565079679130577" id="master_svg1_73_6481"><stop offset="0%" stop-color="#0058FF" stop-opacity="0"/><stop offset="100%" stop-color="#00AAFF" stop-opacity="0.5"/></linearGradient><linearGradient x1="0" y1="0.5" x2="1.0000001192092896" y2="0.5" id="master_svg2_73_6482"><stop offset="0%" stop-color="#0066FF" stop-opacity="1"/><stop offset="12.5%" stop-color="#0066FF" stop-opacity="1"/><stop offset="49.73750710487366%" stop-color="#87D4FF" stop-opacity="1"/><stop offset="91.14583134651184%" stop-color="#0075FF" stop-opacity="1"/></linearGradient><linearGradient x1="0.5000787973403931" y1="0.9994168281555176" x2="0.5000787973403931" y2="0" id="master_svg3_85_5542"><stop offset="0%" stop-color="#00C9FF" stop-opacity="1"/><stop offset="100%" stop-color="#0072DD" stop-opacity="1"/></linearGradient><linearGradient x1="0.5" y1="0" x2="0.5" y2="1" id="master_svg4_13_2583"><stop offset="0%" stop-color="#FFFFFF" stop-opacity="0"/><stop offset="100%" stop-color="#FFFFFF" stop-opacity="1"/></linearGradient><linearGradient x1="0.5000787973403931" y1="0.9994168281555176" x2="0.5000787973403931" y2="0" id="master_svg5_85_5542"><stop offset="0%" stop-color="#00C9FF" stop-opacity="1"/><stop offset="100%" stop-color="#0072DD" stop-opacity="1"/></linearGradient><linearGradient x1="0.5000787973403931" y1="0.9994168281555176" x2="0.5000787973403931" y2="0" id="master_svg6_85_5542"><stop offset="0%" stop-color="#00C9FF" stop-opacity="1"/><stop offset="100%" stop-color="#0072DD" stop-opacity="1"/></linearGradient><linearGradient x1="0.5" y1="0" x2="0.5" y2="1" id="master_svg7_13_2583"><stop offset="0%" stop-color="#FFFFFF" stop-opacity="0"/><stop offset="100%" stop-color="#FFFFFF" stop-opacity="1"/></linearGradient></defs><g><g style="opacity:0.30000001192092896;"><path d="M1,111C1,113.761,3.23858,116,6,116L49,116C51.7614,116,54,113.761,54,111L54,4L1,4L1,111Z" fill="url(#master_svg0_85_7578)" fill-opacity="1"/></g><g><rect x="1" y="85" width="53" height="30" rx="0" fill="url(#master_svg1_73_6481)" fill-opacity="1" id="pw1" /><rect id="pw2" x="1" y="85" width="53" height="30" rx="0" fill="url(#master_svg2_73_6482)" fill-opacity="0.6000000238418579"/></g><g><ellipse cx="27.5" cy="5" rx="26.5" ry="5" fill="url(#master_svg3_85_5542)" fill-opacity="1"/></g><g><path d="M53.3333,5C53.3333,5.498801,52.8377,6.0743100000000005,51.576,6.68445C50.3307,7.28672,48.4753,7.85205,46.1077,8.33633C41.3823,9.30283,34.8033,9.909089999999999,27.5,9.909089999999999C27.5,9.909089999999999,27.5,11,27.5,11C34.924,11,41.6783,10.38521,46.6047,9.37758C49.063,8.87476,51.1127,8.26474,52.5663,7.56187C54.0033,6.86686,55,6.00743,55,5C55,5,53.3333,5,53.3333,5C53.3333,5,53.3333,5,53.3333,5ZM27.5,9.909089999999999C20.1965,9.909089999999999,13.6176,9.30283,8.89237,8.33633C6.52483,7.85205,4.6695,7.28672,3.42413,6.68445C2.16246,6.0743100000000005,1.66667,5.498801,1.66667,5C1.66667,5,0,5,0,5C0,6.00743,0.996595,6.86686,2.43374,7.56187C3.88718,8.26474,5.9371,8.87476,8.39527,9.37758C13.3215,10.38521,20.0759,11,27.5,11C27.5,11,27.5,9.909089999999999,27.5,9.909089999999999C27.5,9.909089999999999,27.5,9.909089999999999,27.5,9.909089999999999Z" fill="url(#master_svg4_13_2583)" fill-opacity="1"/></g><g><ellipse id="ellipse1" cx="27.5" cy="85" rx="26.5" ry="5" fill="url(#master_svg5_85_5542)" fill-opacity="1"/></g><g><ellipse cx="27.5" cy="115" rx="26.5" ry="5" fill="url(#master_svg6_85_5542)" fill-opacity="1"/></g><g><path d="M53.3333,115C53.3333,115.498801,52.8377,116.07431,51.576,116.68445C50.3307,117.28672,48.4753,117.85205,46.1077,118.33633C41.3823,119.30283,34.8033,119.90909,27.5,119.90909C27.5,119.90909,27.5,121,27.5,121C34.924,121,41.6783,120.38521,46.6047,119.37758C49.063,118.87476,51.1127,118.26474,52.5663,117.56187C54.0033,116.86686,55,116.00743,55,115C55,115,53.3333,115,53.3333,115C53.3333,115,53.3333,115,53.3333,115ZM27.5,119.90909C20.1965,119.90909,13.6176,119.30283,8.89237,118.33633C6.52483,117.85205,4.6695,117.28672,3.42413,116.68445C2.16246,116.07431,1.66667,115.498801,1.66667,115C1.66667,115,0,115,0,115C0,116.00743,0.996595,116.86686,2.43374,117.56187C3.88718,118.26474,5.9371,118.87476,8.39527,119.37758C13.3215,120.38521,20.0759,121,27.5,121C27.5,121,27.5,119.90909,27.5,119.90909C27.5,119.90909,27.5,119.90909,27.5,119.90909Z" fill="url(#master_svg7_13_2583)" fill-opacity="1"/></g></g></svg>

After

Width:  |  Height:  |  Size: 4.6 KiB

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="312.5" height="210.75" viewBox="0 0 312.5 210.75"><defs><linearGradient x1="0.5" y1="0" x2="0.5" y2="1" id="master_svg0_95_7905"><stop offset="0%" stop-color="#23518C" stop-opacity="0.20000000298023224"/><stop offset="100%" stop-color="#17439D" stop-opacity="0.10000000149011612"/></linearGradient><radialGradient cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" id="master_svg1_95_7906" gradientTransform="translate(156.25 210.5) rotate(90) scale(33.016276359558105 168.4368994986062)"><stop offset="0%" stop-color="#2773FF" stop-opacity="0.10000000149011612"/><stop offset="100%" stop-color="#2773FF" stop-opacity="0"/></radialGradient><radialGradient cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" id="master_svg2_95_7907" gradientTransform="translate(156.25 210.5) rotate(90) scale(7.3813605308532715 97.69471740388508)"><stop offset="0%" stop-color="#2773FF" stop-opacity="0.20000000298023224"/><stop offset="100%" stop-color="#2773FF" stop-opacity="0"/></radialGradient><radialGradient cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" id="master_svg3_95_7908" gradientTransform="translate(156.25 210.5) rotate(90) scale(3.5998570919036865 69.85723328462429)"><stop offset="0%" stop-color="#2773FF" stop-opacity="0.5"/><stop offset="100%" stop-color="#2773FF" stop-opacity="0"/></radialGradient><linearGradient x1="0.5" y1="0.05106060206890106" x2="0.5" y2="1" id="master_svg4_81_5443"><stop offset="0%" stop-color="#525DFF" stop-opacity="0"/><stop offset="100%" stop-color="#525DFF" stop-opacity="0.47999998927116394"/></linearGradient><radialGradient cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" id="master_svg5_13_2169" gradientTransform="translate(139.9359314441681 0.5) rotate(0) scale(4.274876832962036 Infinity)"><stop offset="0%" stop-color="#4FE4FF" stop-opacity="1"/><stop offset="100%" stop-color="#2773FF" stop-opacity="0"/></radialGradient><linearGradient x1="1" y1="0.5" x2="0" y2="0.5" id="master_svg6_13_2170"><stop offset="0%" stop-color="#36C8FF" stop-opacity="0"/><stop offset="53.635478019714355%" stop-color="#27AEFF" stop-opacity="1"/><stop offset="100%" stop-color="#1997FF" stop-opacity="0.20000000298023224"/></linearGradient></defs><g><g><path d="M0.25,0.5L312.25,0.5L312.25,210.5L0.25,210.5L0.25,0.5Z" fill-rule="evenodd" fill="#000000" fill-opacity="0.25"/><path d="M0.25,0.5L312.25,0.5L312.25,210.5L0.25,210.5L0.25,0.5Z" fill-rule="evenodd" fill="url(#master_svg0_95_7905)" fill-opacity="1"/><path d="M0.25,0.5L312.25,0.5L312.25,210.5L0.25,210.5L0.25,0.5Z" fill-rule="evenodd" fill="url(#master_svg1_95_7906)" fill-opacity="1"/><path d="M0.25,0.5L312.25,0.5L312.25,210.5L0.25,210.5L0.25,0.5Z" fill-rule="evenodd" fill="url(#master_svg2_95_7907)" fill-opacity="1"/><path d="M0.25,0.5L312.25,0.5L312.25,210.5L0.25,210.5L0.25,0.5Z" fill-rule="evenodd" fill="url(#master_svg3_95_7908)" fill-opacity="1"/><path d="M312.5,0.25L0,0.25L0,210.75L312.5,210.75L312.5,0.25ZM0.5,210.25L0.5,0.75L312,0.75L312,210.25L0.5,210.25Z" fill-rule="evenodd" fill="url(#master_svg4_81_5443)" fill-opacity="1"/></g><g style="opacity:0.4000000059604645;"><path d="M312.25,1L220.432,1L177.243,1L0.25,1L0.25,0L177.243,0L220.432,0L312.25,0L312.25,1Z" fill-rule="evenodd" fill="url(#master_svg5_13_2169)" fill-opacity="1"/><path d="M312.25,1L220.432,1L177.243,1L0.25,1L0.25,0L177.243,0L220.432,0L312.25,0L312.25,1Z" fill-rule="evenodd" fill="url(#master_svg6_13_2170)" fill-opacity="1"/></g></g></svg>

After

Width:  |  Height:  |  Size: 3.5 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 6.6 KiB

View File

@ -1,5 +0,0 @@
<template>
</template>
<script lang="ts" setup></script>

View File

@ -1,315 +0,0 @@
<template>
<div class="chart-container" v-echartResize>
<div class="chart" ref="chartRef"></div>
<!-- 底座背景 -->
<div class="bg"></div>
<!-- 中间文字 -->
<div class="center-text">
<div class="value">{{ totalValue }}</div>
<div class="unit"></div>
</div>
</div>
</template>
<script setup>
import { ref, onMounted, onBeforeUnmount, reactive, computed } from 'vue'
import { getPie3D, getParametricEquation } from '@/composables/useEchart'
import * as echarts from 'echarts'
import 'echarts-gl' // 3d
import { fitChartSize } from '@/utils/echartData'
import { vEchartResize } from '@/directives/chart-resize'
const color = ['#5AF3B8', '#93DBFF']
const props = defineProps({
optionData: {
type: Array,
default: () => []
}
})
// refs
const chartRef = ref(null)
let statusChart = ref(null)
//
const totalValue = computed(() => {
return props.optionData.reduce((sum, item) => sum + item.value, 0)
})
const option = reactive({})
// label
const setLabel = () => {
props.optionData.forEach((item, index) => {
item.itemStyle = {
color: color[index]
}
item.label = {
show: true,
color: color[index],
formatter: '{b} {d}%', // 使join
rich: {
b: {
color: color[index],
lineHeight: 25,
align: 'left',
fontSize: 12,
},
d: {
color: color[index],
align: 'left',
fontSize: 12
}
}
}
item.labelLine = {
lineStyle: {
width: 1,
color: color[index]
}
}
})
}
//
const initChart = () => {
statusChart.value = echarts.init(chartRef.value)
// option, 3d,
Object.assign(option, getPie3D(props.optionData, 0.8, 240, 36, 13, 0.5))
statusChart.value.setOption(option)
// label线2d使labelLine3dsetOption
option.series.push({
name: '', //
backgroundColor: 'transparent',
type: 'pie',
label: {
opacity: 1,
fontSize: 12,
},
startAngle: -40, // [0, 360]
clockwise: false, // 3d
radius: ['20%', '50%'],
center: ['50%', '50%'],
data: props.optionData,
itemStyle: {
opacity: 0 //02d
}
})
statusChart.value.setOption(option)
bindListen(statusChart.value)
}
//
// optionNameoptionopiton
const bindListen = (myChart) => {
let selectedIndex = ''
let hoveredIndex = ''
//
myChart.on('click', (params) => {
// params.seriesIndex
if (params.seriesIndex === undefined || !option.series[params.seriesIndex] || !option.series[params.seriesIndex].pieStatus) {
return;
}
// option.series
const isSelected = !option.series[params.seriesIndex].pieStatus.selected
const isHovered = option.series[params.seriesIndex].pieStatus.hovered
const k = option.series[params.seriesIndex].pieStatus.k
const startRatio = option.series[params.seriesIndex].pieData.startRatio
const endRatio = option.series[params.seriesIndex].pieData.endRatio
// option
if (selectedIndex !== '' && selectedIndex !== params.seriesIndex &&
option.series[selectedIndex] && option.series[selectedIndex].pieStatus) {
option.series[selectedIndex].parametricEquation = getParametricEquation(
option.series[selectedIndex].pieData.startRatio,
option.series[selectedIndex].pieData.endRatio,
false,
false,
k,
option.series[selectedIndex].pieData.value
)
option.series[selectedIndex].pieStatus.selected = false
}
// / option
option.series[params.seriesIndex].parametricEquation = getParametricEquation(
startRatio,
endRatio,
isSelected,
isHovered,
k,
option.series[params.seriesIndex].pieData.value
)
option.series[params.seriesIndex].pieStatus.selected = isSelected
// seriesIndex
selectedIndex = isSelected ? params.seriesIndex : null
// 使 option
myChart.setOption(option)
})
// mouseover
myChart.on('mouseover', (params) => {
//
let isSelected
let isHovered
let startRatio
let endRatio
let k
// mouseover
if (hoveredIndex === params.seriesIndex) {
//
} else {
// option
if (hoveredIndex !== '' && option.series[hoveredIndex] && option.series[hoveredIndex].pieStatus) {
// option.series false
isSelected = option.series[hoveredIndex].pieStatus.selected
isHovered = false
startRatio = option.series[hoveredIndex].pieData.startRatio
endRatio = option.series[hoveredIndex].pieData.endRatio
k = option.series[hoveredIndex].pieStatus.k
// option
option.series[hoveredIndex].parametricEquation = getParametricEquation(
startRatio,
endRatio,
isSelected,
isHovered,
k,
option.series[hoveredIndex].pieData.value
)
option.series[hoveredIndex].pieStatus.hovered = isHovered
// seriesIndex
hoveredIndex = ''
}
// mouseover option
if (
params.seriesName !== 'mouseoutSeries' &&
params.seriesName !== 'pie2d' &&
params.seriesIndex !== undefined &&
option.series[params.seriesIndex] &&
option.series[params.seriesIndex].pieStatus
) {
// option.series true
isSelected = option.series[params.seriesIndex].pieStatus.selected
isHovered = true
startRatio = option.series[params.seriesIndex].pieData.startRatio
endRatio = option.series[params.seriesIndex].pieData.endRatio
k = option.series[params.seriesIndex].pieStatus.k
// option
option.series[params.seriesIndex].parametricEquation = getParametricEquation(
startRatio,
endRatio,
isSelected,
isHovered,
k,
option.series[params.seriesIndex].pieData.value + 60
)
option.series[params.seriesIndex].pieStatus.hovered = isHovered
// seriesIndex
hoveredIndex = params.seriesIndex
}
// 使 option
myChart.setOption(option)
}
})
// bug
myChart.on('globalout', () => {
//
let isSelected
let isHovered
let startRatio
let endRatio
let k
if (hoveredIndex !== '' && option.series[hoveredIndex] && option.series[hoveredIndex].pieStatus) {
// option.series true
isSelected = option.series[hoveredIndex].pieStatus.selected
isHovered = false
k = option.series[hoveredIndex].pieStatus.k
startRatio = option.series[hoveredIndex].pieData.startRatio
endRatio = option.series[hoveredIndex].pieData.endRatio
// option
option.series[hoveredIndex].parametricEquation = getParametricEquation(
startRatio,
endRatio,
isSelected,
isHovered,
k,
option.series[hoveredIndex].pieData.value
)
option.series[hoveredIndex].pieStatus.hovered = isHovered
// seriesIndex
hoveredIndex = ''
}
// 使 option
myChart.setOption(option)
})
}
//
// const changeSize = () => {
// statusChart.value?.resize()
// }
//
onMounted(() => {
setLabel()
initChart()
//
// window.addEventListener('resize', changeSize)
})
// onBeforeUnmount(() => {
// window.removeEventListener('resize', changeSize)
// })
</script>
<style lang='scss' scoped>
.chart-container {
position: relative;
width: 100%;
height: 100%;
.chart,
.bg {
width: 100%;
height: 100%;
}
.bg {
position: absolute;
bottom: 50px;
left: 50%;
z-index: -1;
width: 180px;
height: 73px;
background: no-repeat center;
background-image: url('/images/particles-bg.png');
background-size: 100% 100%;
transform: translateX(-50%);
}
.center-text {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
z-index: 10;
text-align: center;
.value {
display: inline-block;
font-size: 24px;
font-weight: 500;
color: #8FC8FF;
}
.unit {
display: inline-block;
font-size: 18px;
font-weight: 500;
color: #FFFFFF;
}
}
}
</style>

View File

@ -0,0 +1,110 @@
<template>
<div class="w-full overflow-x-auto ranking-table">
<table :style="tableStyle">
<!-- 表头插槽 -->
<thead v-if="$slots.header">
<tr>
<th :colspan="columns.length">
<slot name="header"></slot>
</th>
</tr>
</thead>
<!-- 列标题 -->
<thead :class="`${headerClass}`">
<tr>
<th v-for="col in columns" :key="col.field" :style="getWidthStyle(col)">
<div :class="`cell-content ${col.align}`">
{{ col.header }}
</div>
</th>
</tr>
</thead>
<tbody :class="`${bodyClass}`">
<tr v-for="(row, rowIndex) in value" :key="rowIndex">
<td v-for="col in columns" :key="col.field" :style="getWidthStyle(col)" :class="`${col.align}`">
<div :class="`cell-content ${col.align}`">
<slot :name="col.field" :data="row" :index="rowIndex">
{{ row[col.field] }}
</slot>
</div>
</td>
</tr>
</tbody>
<!-- 表尾插槽 -->
<tfoot v-if="$slots.footer">
<tr>
<td :colspan="columns.length">
<slot name="footer"></slot>
</td>
</tr>
</tfoot>
</table>
</div>
</template>
<script lang="ts" setup>
interface Column {
field: string;
header: string;
width?: string;
minWidth?: string;
maxWidth?: string;
align?: string;
}
interface Props {
value: any[];
columns: Column[];
tableStyle?: string;
headerClass?: string;
bodyClass?:string;
}
defineProps<Props>();
const getWidthStyle = (col: Column) => {
const style: Record<string, string> = {};
if (col.width) style.width = col.width;
if (col.minWidth) style.minWidth = col.minWidth;
if (col.maxWidth) style.maxWidth = col.maxWidth;
return style;
};
</script>
<style scoped lang="scss">
table {
width: 100%;
border-collapse: collapse;
border-spacing: 0;
}
th,
td {
color: #fff;
}
.cell-content {
display: flex;
align-items: center;
width: 100%;
}
tr:hover td {
background: rgba(255, 255, 255, 0.05);
}
/* 自定义滚动条样式 */
.ranking-table::-webkit-scrollbar {
width: 6px;
height: 6px;
}
.ranking-table::-webkit-scrollbar-thumb {
background: rgba(255, 255, 255, 0.2);
border-radius: 3px;
}
.ranking-table::-webkit-scrollbar-track {
background: rgba(0, 0, 0, 0.1);
}
</style>

View File

@ -9,7 +9,7 @@
}
html {
line-height: 1.15;
line-height: 1;
-webkit-text-size-adjust: 100%;
}
body {

View File

@ -0,0 +1,11 @@
.border-image {
border: 1px solid;
border-image: linear-gradient(
90deg,
#217ac600,
#227cc8,
#217ac600
)
1 1;
opacity: 0.3;
}

View File

@ -0,0 +1,59 @@
<template>
<div class="w-[926px] h-[358px] relative bg-[#082059]">
<div class="flex h-full custom-border absolute top-0 left-0">
<div class="relative h-[36px]">
<div class="absolute top-[50%] translate-y-[-50%] left-[15px] flex items-center">
<SvgComponent :content="arrowLeftSvg" class="w-[15px] h-[18px]" />
<div class="bg-gradient-to-b from-[#8FC8FF] to-white bg-clip-text text-transparent text-[20px] ml-[9px] font-700">咨询学段</div>
</div>
<SvgComponent :content="headerLeftSvg" class="w-[255px] h-[36px]" />
</div>
<SvgComponent :content="headerRightSvg" class="w-[669px] h-[36px]" />
</div>
<div class="w-full h-[calc(100%-36px)] mt-[36px]">
<AskSectionChart />
</div>
</div>
</template>
<script setup lang="ts">
import SvgComponent from "@/components/SvgComponent.vue";
import AskSectionChart from "@/views/components/chartsComponents/AskSectionChart.vue";
const headerLeftSvg = ref("");
const headerRightSvg = ref("");
const getHeaderLeftSvg = async () => {
const { default: svg } = await import("/src/assets/svg-img/header-bg-left.svg?raw");
headerLeftSvg.value = svg;
};
const getHeaderRightSvg = async () => {
const { default: svg } = await import("/src/assets/svg-img/header-bg-right.svg?raw");
headerRightSvg.value = svg;
};
const arrowLeftSvg = ref("");
const getArrowLeftSvg = async () => {
const { default: svg } = await import("/src/assets/svg-img/arrow-left.svg?raw");
arrowLeftSvg.value = svg;
};
onBeforeMount(() => {
getHeaderLeftSvg();
getHeaderRightSvg();
getArrowLeftSvg();
});
</script>
<style scoped lang="scss">
.custom-border {
border-image-slice: 27 27 27 27;
border-image-width: 1px 1px 2px 1px;
border-image-outset: 0px 0px 0px 0px;
border-image-repeat: stretch stretch;
border-image-source: url("src/assets/svg-img/border-image.png");
border-style: solid;
}
</style>

View File

@ -0,0 +1,108 @@
<template>
<div class="border-container">
<div class="border-glow"></div>
<div class="border-inner p-[2px]">
<slot></slot>
</div>
</div>
</template>
<script>
export default {
name: "BackgroundColor",
data() {
return {
animationFrame: null,
};
},
mounted() {
this.startAnimation();
},
beforeUnmount() {
if (this.animationFrame) {
cancelAnimationFrame(this.animationFrame);
}
},
methods: {
startAnimation() {
const borderGlow = document.querySelector(".border-glow");
let angle = 0;
const animate = () => {
angle = (angle + 1) % 360;
if (borderGlow) {
borderGlow.style.background = `conic-gradient(
from ${angle}deg,
hsla(0, 0%, 0%, 0.25),
hsla(214, 60%, 34%, 0.2),
hsla(220, 74%, 35%, 0.1),
hsla(219, 100%, 58%, 0.1),
hsla(219, 100%, 58%, 0.2),
hsla(219, 100%, 58%, 0.5),
hsla(219, 100%, 58%, 0)
)`;
}
this.animationFrame = requestAnimationFrame(animate);
};
animate();
},
},
};
</script>
<style scoped>
.border-container {
position: relative;
border-radius: 4px;
overflow: hidden;
}
.border-glow {
position: absolute;
top: -2px;
left: -2px;
right: -2px;
bottom: -2px;
width: auto;
height: auto;
background: conic-gradient(
from 0deg,
hsla(0, 0%, 0%, 0.25),
hsla(214, 60%, 34%, 0.2),
hsla(220, 74%, 35%, 0.1),
hsla(219, 100%, 58%, 0.1),
hsla(219, 100%, 58%, 0.2),
hsla(219, 100%, 58%, 0.5),
hsla(219, 100%, 58%, 0)
);
border-radius: inherit;
filter: blur(2px);
pointer-events: none;
mix-blend-mode: plus-lighter;
z-index: 0;
}
.border-inner {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
width: 100%;
height: 100%;
border: 0.5px solid hsla(236, 100%, 66%, 0.48);
border-radius: inherit;
pointer-events: none;
box-sizing: border-box;
}
/* 内容区域样式 */
.border-container > :not(.border-glow):not(.border-inner) {
position: relative;
z-index: 1;
height: 100%;
width: 100%;
box-sizing: border-box;
}
</style>

View File

@ -0,0 +1,133 @@
<template>
<div class="w-[296px] h-[320px] relative bg-[#082059]">
<div class="flex h-full custom-border absolute top-0 left-0">
<div class="relative h-[36px]">
<div class="absolute top-[50%] translate-y-[-50%] left-[15px] flex items-center">
<SvgComponent :content="arrowLeftSvg" class="w-[15px] h-[18px]" />
<div class="bg-gradient-to-b from-[#8FC8FF] to-white bg-clip-text text-transparent text-[20px] ml-[9px] font-700">收费排行榜</div>
</div>
<SvgComponent :content="headerLeftSvg" class="w-[188px] h-[36px]" />
</div>
<SvgComponent :content="headerRightSvg" class="w-[108px] h-[36px]" />
</div>
<div class="w-full h-[calc(100%-36px)] mt-[36px] flex flex-col relative">
<div class="absolute right-[0] flex items-center justify-end mr-[13px] transform-translate-y-[-50%]">
<div class="text-[15px] text-[#84E8FF]">更多</div>
<SvgComponent :content="moreArrowSvg" class="w-[14px] h-[22px]" />
</div>
<div class="mt-[26px] mx-[16px]">
<RankingTable :value="products" :columns="columns" header-class="custom-table-header" body-class="custom-table-body">
<template #rank="{ index }">
<SvgComponent :content="goldMedalSvg" class="w-[34px] h-[20px]" v-if="index === 0" />
<SvgComponent :content="silverMedalSvg" class="w-[34px] h-[20px]" v-if="index === 1" />
<SvgComponent :content="bronzeMedalSvg" class="w-[34px] h-[20px]" v-if="index === 2" />
<span class="text-[14px] font-600" v-if="index > 2">{{ index + 1 }}</span>
</template>
<template #name="{ data }">
<span class="text-[#C0EEFF] text-[14px]">{{ data.name }}</span>
</template>
</RankingTable>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import SvgComponent from "@/components/SvgComponent.vue";
import RankingTable from "@/components/table/RankingTable.vue";
const columns = [
{ field: "rank", header: "名次", align: "justify-center", width: "68px" },
{ field: "name", header: "姓名", align: "justify-left", width: "100px" },
{ field: "Status", header: "获客人数", align: "justify-center", width: "96px" },
];
const products = [{ name: "张三" }, { name: "张三" }, { name: "张三" }, { name: "张三" }, { name: "张三" }];
const headerLeftSvg = ref("");
const headerRightSvg = ref("");
const getHeaderLeftSvg = async () => {
const { default: svg } = await import("/src/assets/svg-img/header-bg-left-sort.svg?raw");
headerLeftSvg.value = svg;
};
const getHeaderRightSvg = async () => {
const { default: svg } = await import("/src/assets/svg-img/header-bg-right-sort.svg?raw");
headerRightSvg.value = svg;
};
const arrowLeftSvg = ref("");
const getArrowLeftSvg = async () => {
const { default: svg } = await import("/src/assets/svg-img/arrow-left.svg?raw");
arrowLeftSvg.value = svg;
};
const moreArrowSvg = ref("");
const getMoreArrowSvg = async () => {
const { default: svg } = await import("/src/assets/svg-img/more-arrow.svg?raw");
moreArrowSvg.value = svg;
};
const goldMedalSvg = ref("");
const getGoldMedalSvg = async () => {
const { default: svg } = await import("/src/assets/svg-img/gold-medal.svg?raw");
goldMedalSvg.value = svg;
};
const silverMedalSvg = ref("");
const getSilverMedalSvg = async () => {
const { default: svg } = await import("/src/assets/svg-img/silver-medal.svg?raw");
silverMedalSvg.value = svg;
};
const bronzeMedalSvg = ref("");
const getBronzeMedalSvg = async () => {
const { default: svg } = await import("/src/assets/svg-img/bronze-medal.svg?raw");
bronzeMedalSvg.value = svg;
};
onBeforeMount(() => {
getHeaderLeftSvg();
getHeaderRightSvg();
getArrowLeftSvg();
getMoreArrowSvg();
getGoldMedalSvg();
getSilverMedalSvg();
getBronzeMedalSvg();
});
</script>
<style scoped lang="scss">
.custom-border {
border-image-slice: 27 27 27 27;
border-image-width: 1px 1px 2px 1px;
border-image-outset: 0px 0px 0px 0px;
border-image-repeat: stretch stretch;
border-image-source: url("src/assets/svg-img/border-image.png");
border-style: solid;
}
:deep(.custom-table-header) {
tr {
background-color: rgb(14, 39, 97);
th {
padding: 13px 10px;
color: #44c1ef;
font-weight: 400;
line-height: 1;
}
}
}
:deep(.custom-table-body) {
tr {
td {
padding: 10px;
line-height: 1;
}
}
}
</style>

View File

@ -0,0 +1,110 @@
<template>
<div class="w-max h-max relative">
<SvgComponent :content="groupSvg" class="w-[312px] h-[210px]" />
<div class="w-full h-full absolute top-0 left-0 pt-[31px] pb-[21px] pl-[14px] pr-[19px] flex items-center">
<div class="w-[144px]">
<div class="relative w-[144px] h-[113px] flex items-center flex-col">
<div class="text-[#44C1EF] italic text-[20px] font-700">今日获客</div>
<div class="bg-gradient-to-b from-[#8FC8FF] to-white bg-clip-text text-transparent mb-[15px] z-10">
<span class="text-[34px] italic">125</span>
<span class="text-[18px]"></span>
</div>
<SvgComponent :content="hexagonalBoxSvg" class="box-light absolute" />
</div>
</div>
<div class="relative ml-[12px]">
<SvgComponent :content="paymentBorderSvg" class="w-[127px] h-[104px] z-1" />
<div class="w-[127px] h-[104px] top-0 left-0 z-1 absolute pl-[14px] flex flex-col justify-center">
<p class="text-[#C0EEFF] text-[12px]">昨日获客人数</p>
<p class="text-[#C0EEFF] text-[16px] font-500 mt-[18px] mb-[9px]">177</p>
<div class="text-[#FF4E4E] text-[12px] flex items-center">
<span class="">今日较昨日</span>
<SvgIcon name="arrow-up" class="text-[9px]" />
<span>12</span>
</div>
</div>
</div>
</div>
</div>
</template>
<script lang="ts" setup>
import SvgComponent from "@/components/SvgComponent.vue";
import SvgIcon from "@/components/svg-icon/SvgIcon.vue";
const groupSvg = ref("");
const getGroupBackgroundSvg = async () => {
const { default: svg } = await import("/src/assets/svg-img/short-background.svg?raw");
groupSvg.value = svg;
};
const hexagonalBoxSvg = ref("");
const getLightningBoxSvg = async () => {
const { default: svg } = await import("/src/assets/svg-img/hexagonal-light.svg?raw");
hexagonalBoxSvg.value = svg;
};
const paymentBorderSvg = ref("");
const getPaymentChartSvg = async () => {
const { default: svg } = await import("/src/assets/svg-img/payment-border.svg?raw");
paymentBorderSvg.value = svg;
};
onBeforeMount(() => {
getGroupBackgroundSvg();
getLightningBoxSvg();
getPaymentChartSvg();
});
</script>
<style scoped lang="scss">
@use "@/styles/text-color.scss";
.border-image {
border: 1px solid;
border-image: linear-gradient(
90deg,
#217ac600,
#227cc8,
#217ac600
)
1 1;
opacity: 0.3;
}
.rotate-animation {
animation: rotate-animation 1s infinite;
}
@keyframes rotate-animation {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(-180deg);
}
}
:deep(.box-light) {
.lightning-flashing {
animation: lightning-flashing 1s infinite;
}
@keyframes lightning-flashing {
0% {
fill-opacity: 0;
}
50% {
fill-opacity: 1;
}
100% {
fill-opacity: 0;
}
}
}
</style>

View File

@ -0,0 +1,117 @@
<template>
<div class="w-max h-max relative">
<SvgComponent :content="groupSvg" class="w-[312px] h-[210px]" />
<div class="w-full h-full absolute top-0 left-0 pt-[31px] pb-[21px] pl-[14px] pr-[19px] flex items-center">
<div class="w-[144px]">
<div class="relative w-[144px] h-[113px] flex items-center flex-col">
<div class="text-[#44C1EF] italic text-[20px] font-700">总获客</div>
<div class="bg-gradient-to-b from-[#8FC8FF] to-white bg-clip-text text-transparent mb-[15px] z-10">
<span class="text-[34px] italic">125</span>
<span class="text-[18px]"></span>
</div>
<SvgComponent :content="hexagonalBoxSvg" class="box-light absolute" />
</div>
</div>
<div class="relative ml-[37px] flex flex-col items-center">
<span class="text-[#C0EEFF] text-[12px]">目标值2W</span>
<SvgComponent :content="powerSvg" class="w-[55px] h-[121px] z-1 my-[4px]" />
<span class="text-[#769CBF] text-[12px]">当前值0.5W</span>
</div>
</div>
</div>
</template>
<script lang="ts" setup>
import SvgComponent from "@/components/SvgComponent.vue";
const groupSvg = ref("");
const getGroupBackgroundSvg = async () => {
const { default: svg } = await import("/src/assets/svg-img/short-background.svg?raw");
groupSvg.value = svg;
};
const hexagonalBoxSvg = ref("");
const getLightningBoxSvg = async () => {
const { default: svg } = await import("/src/assets/svg-img/hexagonal-light.svg?raw");
hexagonalBoxSvg.value = svg;
};
const powerFlag = ref(false)
const powerSvg = ref("");
const getPaymentChartSvg = async () => {
const { default: svg } = await import("/src/assets/svg-img/process.svg?raw");
powerSvg.value = svg;
powerFlag.value = true;
};
const setChargePercentageByPath = (percent: number) => {
// 55 121
// y="85" height="30"
const pw1 = document.querySelector("g rect#pw1");
const pw2 = document.querySelector("g rect#pw2");
const ellipse1 = document.querySelector("g ellipse#ellipse1");
if(pw1 && pw2 && ellipse1) {
let rectY = percent / 100 * (85 + 30)
pw1.setAttribute("y", `${85 + 30 - rectY} `)
pw1.setAttribute("height", `${rectY}`)
pw2.setAttribute("y", `${85 + 30 - rectY}`)
pw2.setAttribute("height", `${rectY}`)
ellipse1.setAttribute("cy", `${85 + 30 - rectY}`)
}
};
watch(powerFlag, () => {
nextTick(() => {
setChargePercentageByPath(80);
});
});
onBeforeMount(() => {
getGroupBackgroundSvg();
getLightningBoxSvg();
getPaymentChartSvg();
});
</script>
<style scoped lang="scss">
@use "@/styles/text-color.scss";
.border-image {
border: 1px solid;
border-image: linear-gradient(90deg, #217ac600, #227cc8, #217ac600) 1 1;
opacity: 0.3;
}
.rotate-animation {
animation: rotate-animation 1s infinite;
}
@keyframes rotate-animation {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(-180deg);
}
}
:deep(.box-light) {
.lightning-flashing {
animation: lightning-flashing 1s infinite;
}
@keyframes lightning-flashing {
0% {
fill-opacity: 0;
}
50% {
fill-opacity: 1;
}
100% {
fill-opacity: 0;
}
}
}
</style>

View File

@ -0,0 +1,109 @@
<template>
<div class="w-max h-max relative">
<SvgComponent :content="groupSvg" class="w-[312px] h-[210px]" />
<div class="w-full h-full absolute top-0 left-0 pt-[31px] pb-[21px] pl-[14px] pr-[19px] flex items-center">
<div class="w-[144px]">
<div class="relative w-[144px] h-[113px] flex items-center flex-col">
<div class="text-[#44C1EF] italic text-[20px] font-700">今日流失</div>
<div class="bg-gradient-to-b from-[#8FC8FF] to-white bg-clip-text text-transparent mb-[15px] z-10">
<span class="text-[34px] italic">125</span>
<span class="text-[18px]"></span>
</div>
<SvgComponent :content="hexagonalBoxSvg" class="box-light absolute" />
</div>
</div>
<div class="relative ml-[12px]">
<SvgComponent :content="paymentBorderSvg" class="w-[127px] h-[104px] z-1" />
<div class="w-[127px] h-[104px] top-0 left-0 z-1 absolute pl-[14px] flex flex-col justify-center">
<p class="text-[#C0EEFF] text-[12px]">总流失人数</p>
<p class="text-[#C0EEFF] text-[16px] font-500 mt-[18px] mb-[9px]">177</p>
<div class="text-[#FF4E4E] text-[12px] flex items-center">
<span class="">今日较昨日</span>
<SvgIcon name="arrow-up" class="text-[9px]" />
<span>12</span>
</div>
</div>
</div>
</div>
</div>
</template>
<script lang="ts" setup>
import SvgComponent from "@/components/SvgComponent.vue";
import SvgIcon from "@/components/svg-icon/SvgIcon.vue";
const groupSvg = ref("");
const getGroupBackgroundSvg = async () => {
const { default: svg } = await import("/src/assets/svg-img/short-background.svg?raw");
groupSvg.value = svg;
};
const hexagonalBoxSvg = ref("");
const getLightningBoxSvg = async () => {
const { default: svg } = await import("/src/assets/svg-img/hexagonal-light.svg?raw");
hexagonalBoxSvg.value = svg;
};
const paymentBorderSvg = ref("");
const getPaymentChartSvg = async () => {
const { default: svg } = await import("/src/assets/svg-img/payment-border.svg?raw");
paymentBorderSvg.value = svg;
};
onBeforeMount(() => {
getGroupBackgroundSvg();
getLightningBoxSvg();
getPaymentChartSvg();
});
</script>
<style scoped lang="scss">
@use "@/styles/text-color.scss";
.border-image {
border: 1px solid;
border-image: linear-gradient(
90deg,
#217ac600,
#227cc8,
#217ac600
)
1 1;
opacity: 0.3;
}
.rotate-animation {
animation: rotate-animation 1s infinite;
}
@keyframes rotate-animation {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(-180deg);
}
}
:deep(.box-light) {
.lightning-flashing {
animation: lightning-flashing 1s infinite;
}
@keyframes lightning-flashing {
0% {
fill-opacity: 0;
}
50% {
fill-opacity: 1;
}
100% {
fill-opacity: 0;
}
}
}
</style>

View File

@ -0,0 +1,102 @@
<template>
<div class="w-[296px] h-[320px] relative bg-[#082059]">
<div class="flex h-full custom-border absolute top-0 left-0">
<div class="relative h-[36px]">
<div class="absolute top-[50%] translate-y-[-50%] left-[15px] flex items-center">
<SvgComponent :content="arrowLeftSvg" class="w-[15px] h-[18px]" />
<div class="bg-gradient-to-b from-[#8FC8FF] to-white bg-clip-text text-transparent text-[20px] ml-[9px] font-700">线下详情</div>
</div>
<SvgComponent :content="headerLeftSvg" class="w-[188px] h-[36px]" />
</div>
<SvgComponent :content="headerRightSvg" class="w-[108px] h-[36px]" />
</div>
<div class="w-full h-[calc(100%-36px)] mt-[36px] flex flex-col">
<div class="ml-[22px] relative mt-[13px]">
<div class="flex items-center justify-center">
<ProportionCharts :chart-data="chartData" class="z-2 relative" />
<SvgComponent :content="paymentChartSvg" class="w-[143px] h-[143px] absolute top-0 left-[50%] z-1 transform-translate-x-[-50%]" />
</div>
<div class="leading-[1] absolute top-[50%] left-[50%] translate-x-[-50%] translate-y-[-50%] z-3 flex items-center flex-col font-700 italic">
<div
class=" bg-gradient-to-b from-[#8FC8FF] to-white bg-clip-text text-transparent flex items-baseline">
<div class="text-[25px] ">
690
</div>
<div class="text-[20px]"></div>
</div>
<div class="text-[#FFFFFF] text-[16px] text-shadow-[0px_2px_2px_rgba(12,32,72,0.42)] mt-[7px]">线下</div>
</div>
</div>
<ul class="px-[24px] grid grid-cols-2 gap-x-[20px] gap-y-[16px] mt-[20px] leading-[1]">
<li class="flex items-center flex-col" v-for="item in chartData" :key="item.name">
<div class="flex items-center justify-between w-full">
<div class="w-[6px] h-[6px] rounded-full" :style="{ backgroundColor: item.color }"></div>
<div class="flex-1 flex items-center text-[#C0EEFF] text-[12px] justify-between">
<span class="ml-[4px] mr-[9px]">{{ item.name }}</span>
<span>{{ item.value }}</span>
</div>
</div>
<div class="border-image w-full mt-[6px]"></div>
</li>
</ul>
</div>
</div>
</template>
<script setup lang="ts">
import SvgComponent from "@/components/SvgComponent.vue";
import ProportionCharts from "@/views/components/chartsComponents/ProportionCharts.vue";
const headerLeftSvg = ref("");
const headerRightSvg = ref("");
const getHeaderLeftSvg = async () => {
const { default: svg } = await import("/src/assets/svg-img/header-bg-left-sort.svg?raw");
headerLeftSvg.value = svg;
};
const getHeaderRightSvg = async () => {
const { default: svg } = await import("/src/assets/svg-img/header-bg-right-sort.svg?raw");
headerRightSvg.value = svg;
};
const paymentChartSvg = ref("");
const getPaymentChartSvg = async () => {
const { default: svg } = await import("/src/assets/svg-img/payment-chart.svg?raw");
paymentChartSvg.value = svg;
};
const arrowLeftSvg = ref("");
const getArrowLeftSvg = async () => {
const { default: svg } = await import("/src/assets/svg-img/arrow-left.svg?raw");
arrowLeftSvg.value = svg;
};
const chartData = ref([
{ name: "类型A", value: 250, color: "#0783FA" },
{ name: "类型B", value: 274, color: "#07D1FA" },
{ name: "类型C", value: 310, color: "#20E6A4" },
{ name: "类型D", value: 135, color: "#FFD15C" },
{ name: "其他", value: 135, color: "#07D1FA" },
]);
onBeforeMount(() => {
getHeaderLeftSvg();
getHeaderRightSvg();
getArrowLeftSvg();
getPaymentChartSvg();
});
</script>
<style scoped lang="scss">
@use "@/styles/custom-border.scss";
.custom-border {
border-image-slice: 27 27 27 27;
border-image-width: 1px 1px 2px 1px;
border-image-outset: 0px 0px 0px 0px;
border-image-repeat: stretch stretch;
border-image-source: url("src/assets/svg-img/border-image.png");
border-style: solid;
}
</style>

View File

@ -0,0 +1,100 @@
<template>
<div class="w-[296px] h-[320px] relative bg-[#082059]">
<div class="flex h-full custom-border absolute top-0 left-0">
<div class="relative h-[36px]">
<div class="absolute top-[50%] translate-y-[-50%] left-[15px] flex items-center">
<SvgComponent :content="arrowLeftSvg" class="w-[15px] h-[18px]" />
<div class="bg-gradient-to-b from-[#8FC8FF] to-white bg-clip-text text-transparent text-[20px] ml-[9px] font-700">线上详情</div>
</div>
<SvgComponent :content="headerLeftSvg" class="w-[188px] h-[36px]" />
</div>
<SvgComponent :content="headerRightSvg" class="w-[108px] h-[36px]" />
</div>
<div class="w-full h-[calc(100%-36px)] mt-[36px] flex flex-col">
<div class="ml-[22px] relative mt-[13px]">
<div class="flex items-center justify-center">
<ProportionCharts :chart-data="chartData" class="z-2 relative" />
<SvgComponent :content="paymentChartSvg" class="w-[143px] h-[143px] absolute top-0 left-[50%] z-1 transform-translate-x-[-50%]" />
</div>
<div class="leading-[1] absolute top-[50%] left-[50%] translate-x-[-50%] translate-y-[-50%] z-3 flex items-center flex-col font-700 italic">
<div
class=" bg-gradient-to-b from-[#8FC8FF] to-white bg-clip-text text-transparent flex items-baseline">
<div class="text-[25px] ">
690
</div>
<div class="text-[20px]"></div>
</div>
<div class="text-[#FFFFFF] text-[16px] text-shadow-[0px_2px_2px_rgba(12,32,72,0.42)] mt-[7px]">线上</div>
</div>
</div>
<ul class="px-[24px] grid grid-cols-2 gap-x-[20px] gap-y-[16px] mt-[20px] leading-[1]">
<li class="flex items-center flex-col" v-for="item in chartData" :key="item.name">
<div class="flex items-center justify-between w-full">
<div class="w-[6px] h-[6px] rounded-full" :style="{ backgroundColor: item.color }"></div>
<div class="flex-1 flex items-center text-[#C0EEFF] text-[12px] justify-between">
<span class="ml-[4px] mr-[9px]">{{ item.name }}</span>
<span>{{ item.value }}</span>
</div>
</div>
<div class="border-image w-full m-[6px]"></div>
</li>
</ul>
</div>
</div>
</template>
<script setup lang="ts">
import SvgComponent from "@/components/SvgComponent.vue";
import ProportionCharts from "@/views/components/chartsComponents/ProportionCharts.vue";
const headerLeftSvg = ref("");
const headerRightSvg = ref("");
const getHeaderLeftSvg = async () => {
const { default: svg } = await import("/src/assets/svg-img/header-bg-left-sort.svg?raw");
headerLeftSvg.value = svg;
};
const getHeaderRightSvg = async () => {
const { default: svg } = await import("/src/assets/svg-img/header-bg-right-sort.svg?raw");
headerRightSvg.value = svg;
};
const paymentChartSvg = ref("");
const getPaymentChartSvg = async () => {
const { default: svg } = await import("/src/assets/svg-img/payment-chart.svg?raw");
paymentChartSvg.value = svg;
};
const arrowLeftSvg = ref("");
const getArrowLeftSvg = async () => {
const { default: svg } = await import("/src/assets/svg-img/arrow-left.svg?raw");
arrowLeftSvg.value = svg;
};
const chartData = ref([
{ name: "类型A", value: 250, color: "#0783FA" },
{ name: "类型B", value: 274, color: "#07D1FA" },
{ name: "类型C", value: 310, color: "#20E6A4" },
{ name: "类型D", value: 135, color: "#FFD15C" },
]);
onBeforeMount(() => {
getHeaderLeftSvg();
getHeaderRightSvg();
getArrowLeftSvg();
getPaymentChartSvg();
});
</script>
<style scoped lang="scss">
@use "@/styles/custom-border.scss";
.custom-border {
border-image-slice: 27 27 27 27;
border-image-width: 1px 1px 2px 1px;
border-image-outset: 0px 0px 0px 0px;
border-image-repeat: stretch stretch;
border-image-source: url("src/assets/svg-img/border-image.png");
border-style: solid;
}
</style>

View File

@ -0,0 +1,58 @@
<template>
<div class="w-[926px] h-[358px] relative bg-[#082059]">
<div class="flex h-full custom-border absolute top-0 left-0">
<div class="relative h-[36px]">
<div class="absolute top-[50%] translate-y-[-50%] left-[15px] flex items-center">
<SvgComponent :content="arrowLeftSvg" class="w-[15px] h-[18px]" />
<div class="bg-gradient-to-b from-[#8FC8FF] to-white bg-clip-text text-transparent text-[20px] ml-[9px] font-700">经营趋势</div>
</div>
<SvgComponent :content="headerLeftSvg" class="w-[255px] h-[36px]" />
</div>
<SvgComponent :content="headerRightSvg" class="w-[669px] h-[36px]" />
</div>
<div class="w-full h-[calc(100%-36px)] mt-[36px]">
<OperatingTrendsChart />
</div>
</div>
</template>
<script setup lang="ts">
import SvgComponent from "@/components/SvgComponent.vue";
import OperatingTrendsChart from "@/views/components/chartsComponents/OperatingTrendsChart.vue";
const headerLeftSvg = ref("");
const headerRightSvg = ref("");
const getHeaderLeftSvg = async () => {
const { default: svg } = await import("/src/assets/svg-img/header-bg-left.svg?raw");
headerLeftSvg.value = svg;
};
const getHeaderRightSvg = async () => {
const { default: svg } = await import("/src/assets/svg-img/header-bg-right.svg?raw");
headerRightSvg.value = svg;
};
const arrowLeftSvg = ref("");
const getArrowLeftSvg = async () => {
const { default: svg } = await import("/src/assets/svg-img/arrow-left.svg?raw");
arrowLeftSvg.value = svg;
};
onBeforeMount(() => {
getHeaderLeftSvg();
getHeaderRightSvg();
getArrowLeftSvg();
});
</script>
<style scoped lang="scss">
.custom-border {
border-image-slice: 27 27 27 27;
border-image-width: 1px 1px 2px 1px;
border-image-outset: 0px 0px 0px 0px;
border-image-repeat: stretch stretch;
border-image-source: url("src/assets/svg-img/border-image.png");
border-style: solid;
}
</style>

View File

@ -50,7 +50,7 @@
<script lang="ts" setup>
import SvgComponent from "@/components/SvgComponent.vue";
import YProgress from "@/components/progress/YProgress.vue";
import ProportionCharts from "@/views/components/ProportionCharts.vue";
import ProportionCharts from "@/views/components/chartsComponents/ProportionCharts.vue";
const groupSvg = ref("");
const getGroupBackgroundSvg = async () => {

View File

@ -0,0 +1,77 @@
<template>
<div class="w-[296px] h-[320px] relative bg-[#082059]">
<div class="flex h-full custom-border absolute top-0 left-0">
<div class="relative h-[36px]">
<div class="absolute top-[50%] translate-y-[-50%] left-[15px] flex items-center">
<SvgComponent :content="arrowLeftSvg" class="w-[15px] h-[18px]" />
<div class="bg-gradient-to-b from-[#8FC8FF] to-white bg-clip-text text-transparent text-[20px] ml-[9px] font-700">六纬志愿</div>
</div>
<SvgComponent :content="headerLeftSvg" class="w-[188px] h-[36px]" />
</div>
<SvgComponent :content="headerRightSvg" class="w-[108px] h-[36px]" />
</div>
<div class="w-full h-[calc(100%-36px)] mt-[36px] flex flex-col relative">
<div class="absolute right-[0] flex items-center justify-end mr-[13px] transform-translate-y-[-50%]">
<div class="text-[15px] text-[#84E8FF]">更多</div>
<SvgComponent :content="moreArrowSvg" class="w-[14px] h-[22px]"/>
</div>
<div class="flex items-baseline leading-[1] mt-[29px] mx-[27px]">
<div class="text-[#44C1EF] italic text-[20px] font-700">总获客</div>
<div class="bg-gradient-to-b from-[#8FC8FF] to-white bg-clip-text text-transparent text-[40px] font-700 italic pr-[4px]">189</div>
<div class="bg-gradient-to-b from-[#8FC8FF] to-white bg-clip-text text-transparent text-[18px] font-700"></div>
<SvgIcon name="arrow-up" class="text-[9px] text-[#4AFFA2] ml-[9px]" />
</div>
<SixStatisticsChart />
</div>
</div>
</template>
<script setup lang="ts">
import SvgComponent from "@/components/SvgComponent.vue";
import SvgIcon from "@/components/svg-icon/SvgIcon.vue";
import SixStatisticsChart from "@/views/components/chartsComponents/SixStatisticsChart.vue";
const headerLeftSvg = ref("");
const headerRightSvg = ref("");
const getHeaderLeftSvg = async () => {
const { default: svg } = await import("/src/assets/svg-img/header-bg-left-sort.svg?raw");
headerLeftSvg.value = svg;
};
const getHeaderRightSvg = async () => {
const { default: svg } = await import("/src/assets/svg-img/header-bg-right-sort.svg?raw");
headerRightSvg.value = svg;
};
const arrowLeftSvg = ref("");
const getArrowLeftSvg = async () => {
const { default: svg } = await import("/src/assets/svg-img/arrow-left.svg?raw");
arrowLeftSvg.value = svg;
};
const moreArrowSvg = ref("");
const getMoreArrowSvg = async () => {
const { default: svg } = await import("/src/assets/svg-img/more-arrow.svg?raw");
moreArrowSvg.value = svg;
};
onBeforeMount(() => {
getHeaderLeftSvg();
getHeaderRightSvg();
getArrowLeftSvg();
getMoreArrowSvg();
});
</script>
<style scoped lang="scss">
.custom-border {
border-image-slice: 27 27 27 27;
border-image-width: 1px 1px 2px 1px;
border-image-outset: 0px 0px 0px 0px;
border-image-repeat: stretch stretch;
border-image-source: url("src/assets/svg-img/border-image.png");
border-style: solid;
}
</style>

View File

@ -0,0 +1,101 @@
<template>
<div class="w-[296px] h-[320px] relative bg-[#082059]">
<div class="flex h-full custom-border absolute top-0 left-0">
<div class="relative h-[36px]">
<div class="absolute top-[50%] translate-y-[-50%] left-[15px] flex items-center">
<SvgComponent :content="arrowLeftSvg" class="w-[15px] h-[18px]" />
<div class="bg-gradient-to-b from-[#8FC8FF] to-white bg-clip-text text-transparent text-[20px] ml-[9px] font-700">学生来源</div>
</div>
<SvgComponent :content="headerLeftSvg" class="w-[188px] h-[36px]" />
</div>
<SvgComponent :content="headerRightSvg" class="w-[108px] h-[36px]" />
</div>
<div class="w-full h-[calc(100%-36px)] mt-[36px] flex flex-col">
<StudentSourceChart
class="w-full h-full"
:chartData="[
{ name: '线下', value: 240, itemStyle: { color: 'rgba(147, 219, 255, 1)' } },
{ name: '线上', value: 600, itemStyle: { color: 'rgb(79, 214, 169)' } },
]"
:ringSize="0.8" />
<div class="flex items-center justify-between mx-[20px] my-[33px]">
<div class="flex items-center">
<SvgComponent :content="onlineSvg" class="w-[53px] h-[38px]" />
<div class="flex flex-col ml-[9px] items-center">
<div class="bg-gradient-to-b from-[#8FC8FF] to-white bg-clip-text text-transparent font-700">
<span class="text-[18px]">240</span>
<span class="text-[14px]"></span>
</div>
<span class="text-[#C7F0FF] text-[12px]">线上来源</span>
</div>
</div>
<div class="flex items-center">
<SvgComponent :content="offlineSvg" class="w-[53px] h-[38px]" />
<div class="flex flex-col ml-[9px] items-center">
<div class="bg-gradient-to-b from-[#8FC8FF] to-white bg-clip-text text-transparent font-700">
<span class="text-[18px]">240</span>
<span class="text-[14px]"></span>
</div>
<span class="text-[#C7F0FF] text-[12px]">线下来源</span>
</div>
</div>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import SvgComponent from "@/components/SvgComponent.vue";
import StudentSourceChart from "@/views/components/chartsComponents/StudentSourceChart.vue";
const headerLeftSvg = ref("");
const headerRightSvg = ref("");
const getHeaderLeftSvg = async () => {
const { default: svg } = await import("/src/assets/svg-img/header-bg-left-sort.svg?raw");
headerLeftSvg.value = svg;
};
const getHeaderRightSvg = async () => {
const { default: svg } = await import("/src/assets/svg-img/header-bg-right-sort.svg?raw");
headerRightSvg.value = svg;
};
const arrowLeftSvg = ref("");
const getArrowLeftSvg = async () => {
const { default: svg } = await import("/src/assets/svg-img/arrow-left.svg?raw");
arrowLeftSvg.value = svg;
};
const onlineSvg = ref("")
const offlineSvg = ref("")
const getOfflineSvg = async () => {
const {default: svg} = await import('/src/assets/svg-img/offline.svg?raw')
offlineSvg.value = svg
}
const getOnlineSvg = async () => {
const {default: svg} = await import('/src/assets/svg-img/online.svg?raw')
onlineSvg.value = svg
}
onBeforeMount(() => {
getHeaderLeftSvg();
getHeaderRightSvg();
getArrowLeftSvg();
getOfflineSvg();
getOnlineSvg();
});
</script>
<style scoped lang="scss">
.custom-border {
border-image-slice: 27 27 27 27;
border-image-width: 1px 1px 2px 1px;
border-image-outset: 0px 0px 0px 0px;
border-image-repeat: stretch stretch;
border-image-source: url("src/assets/svg-img/border-image.png");
border-style: solid;
}
</style>

View File

@ -1,8 +1,8 @@
<template>
<div class="w-max h-max relative">
<SvgComponent :content="groupSvg" class="w-[544px] h-[210px]" />
<SvgComponent :content="groupSvg" class="w-[312px] h-[210px]" />
<div class="w-full h-full absolute top-0 left-0 pt-[31px] pb-[21px] pl-[14px] pr-[19px] flex items-center">
<div class="w-[216px]">
<div class="w-[144px]">
<div class="relative w-[144px] h-[113px] flex items-center flex-col">
<div class="text-[#44C1EF] italic text-[20px] font-700">今日缴费</div>
<div class="bg-gradient-to-b from-[#8FC8FF] to-white bg-clip-text text-transparent mb-[15px] z-10">
@ -11,34 +11,33 @@
</div>
<SvgComponent :content="hexagonalBoxSvg" class="box-light absolute" />
</div>
<div>
<div class="flex items-center justify-between text-[12px]">
<div class="text-[#6B89BC]">当前值1265人</div>
<div class="text-[#69D4FF]">
计划:
<span class="text-[15px]">4000</span>
<span class="text-[13px]"></span>
</div>
</div>
<div class="relative ml-[12px]">
<SvgComponent :content="paymentBorderSvg" class="w-[127px] h-[104px] z-1" />
<div class="w-[127px] h-[104px] top-0 left-0 z-1 absolute pl-[14px] flex flex-col justify-center">
<p class="text-[#C0EEFF] text-[12px]">昨日缴费人数</p>
<p class="text-[#C0EEFF] text-[16px] font-500 mt-[18px] mb-[9px]">177</p>
<div class="text-[#FF4E4E] text-[12px] flex items-center">
<span class="">今日较昨日</span>
<SvgIcon name="arrow-up" class="text-[9px]" />
<span>12</span>
</div>
</div>
</div>
<div class="ml-[22px] relative">
<SvgComponent :content="paymentBorderSvg" class="w-[127px] h-[130px] top-0 left-0 z-1" />
</div>
</div>
</div>
</template>
<script lang="ts" setup>
import SvgComponent from "@/components/SvgComponent.vue";
import SvgIcon from "@/components/svg-icon/SvgIcon.vue";
const groupSvg = ref("");
const getGroupBackgroundSvg = async () => {
const { default: svg } = await import("/src/assets/svg-img/group-background.svg?raw");
const { default: svg } = await import("/src/assets/svg-img/short-background.svg?raw");
groupSvg.value = svg;
};
@ -65,18 +64,7 @@
<style scoped lang="scss">
@use "@/styles/text-color.scss";
.border-image {
border: 1px solid;
border-image: linear-gradient(
90deg,
#217ac600,
#227cc8,
#217ac600
)
1 1;
opacity: 0.3;
}
@use "@/styles/custom-border.scss";
.rotate-animation {
animation: rotate-animation 1s infinite;

View File

@ -0,0 +1,136 @@
<template>
<div class="w-[296px] h-[320px] relative bg-[#082059]">
<div class="flex h-full custom-border absolute top-0 left-0">
<div class="relative h-[36px]">
<div class="absolute top-[50%] translate-y-[-50%] left-[15px] flex items-center">
<SvgComponent :content="arrowLeftSvg" class="w-[15px] h-[18px]" />
<div class="bg-gradient-to-b from-[#8FC8FF] to-white bg-clip-text text-transparent text-[20px] ml-[9px] font-700">获客排行榜</div>
</div>
<SvgComponent :content="headerLeftSvg" class="w-[188px] h-[36px]" />
</div>
<SvgComponent :content="headerRightSvg" class="w-[108px] h-[36px]" />
</div>
<div class="w-full h-[calc(100%-36px)] mt-[36px] flex flex-col relative">
<div class="absolute right-[0] flex items-center justify-end mr-[13px] transform-translate-y-[-50%]">
<div class="text-[15px] text-[#84E8FF]">更多</div>
<SvgComponent :content="moreArrowSvg" class="w-[14px] h-[22px]" />
</div>
<div class="mt-[26px] mx-[16px]">
<RankingTable :value="products" :columns="columns" header-class="custom-table-header" body-class="custom-table-body">
<template #rank="{index }">
<SvgComponent :content="goldMedalSvg" class="w-[34px] h-[20px]" v-if="index===0"/>
<SvgComponent :content="silverMedalSvg" class="w-[34px] h-[20px]" v-if="index===1"/>
<SvgComponent :content="bronzeMedalSvg" class="w-[34px] h-[20px]" v-if="index===2"/>
<span class="text-[14px] font-600" v-if="index > 2">{{ index + 1 }}</span>
</template>
<template #name="{data}">
<span class="text-[#C0EEFF] text-[14px]">{{ data.name }}</span>
</template>
</RankingTable>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import SvgComponent from "@/components/SvgComponent.vue";
import RankingTable from "@/components/table/RankingTable.vue";
const columns = [
{ field: "rank", header: "名次", align: "justify-center",width:'68px' },
{ field: "name", header: "姓名", align: "justify-left",width:'100px' },
{ field: "Status", header: "获客人数", align: "justify-center",width:'96px' },
];
const products = [{ name: "张三" },{ name: "张三" },{ name: "张三" },{ name: "张三" },{ name: "张三" }];
const headerLeftSvg = ref("");
const headerRightSvg = ref("");
const getHeaderLeftSvg = async () => {
const { default: svg } = await import("/src/assets/svg-img/header-bg-left-sort.svg?raw");
headerLeftSvg.value = svg;
};
const getHeaderRightSvg = async () => {
const { default: svg } = await import("/src/assets/svg-img/header-bg-right-sort.svg?raw");
headerRightSvg.value = svg;
};
const arrowLeftSvg = ref("");
const getArrowLeftSvg = async () => {
const { default: svg } = await import("/src/assets/svg-img/arrow-left.svg?raw");
arrowLeftSvg.value = svg;
};
const moreArrowSvg = ref("");
const getMoreArrowSvg = async () => {
const { default: svg } = await import("/src/assets/svg-img/more-arrow.svg?raw");
moreArrowSvg.value = svg;
};
const goldMedalSvg = ref("")
const getGoldMedalSvg = async () => {
const {default: svg} = await import("/src/assets/svg-img/gold-medal.svg?raw");
goldMedalSvg.value = svg
}
const silverMedalSvg = ref("")
const getSilverMedalSvg = async () => {
const {default: svg} = await import("/src/assets/svg-img/silver-medal.svg?raw");
silverMedalSvg.value = svg
}
const bronzeMedalSvg = ref("")
const getBronzeMedalSvg = async () => {
const {default: svg} = await import("/src/assets/svg-img/bronze-medal.svg?raw");
bronzeMedalSvg.value = svg
}
onBeforeMount(() => {
getHeaderLeftSvg();
getHeaderRightSvg();
getArrowLeftSvg();
getMoreArrowSvg();
getGoldMedalSvg();
getSilverMedalSvg();
getBronzeMedalSvg();
});
</script>
<style scoped lang="scss">
.custom-border {
border-image-slice: 27 27 27 27;
border-image-width: 1px 1px 2px 1px;
border-image-outset: 0px 0px 0px 0px;
border-image-repeat: stretch stretch;
border-image-source: url("src/assets/svg-img/border-image.png");
border-style: solid;
}
:deep(.custom-table-header) {
tr{
background-color: rgb(14, 39, 97);
th{
padding: 13px 10px;
color:#44C1EF;
font-weight: 400;
line-height: 1;
}
}
}
:deep(.custom-table-body){
tr{
td{
padding: 10px;
line-height: 1;
}
}
}
</style>

View File

@ -0,0 +1,265 @@
<template>
<div ref="chartDom" class="w-full h-full"></div>
</template>
<script setup lang="ts">
import * as echarts from "echarts";
import { ref, onMounted, onUnmounted } from "vue";
const renderItem = (params: any, api: { coord: (arg0: any[]) => any[]; value: (arg0: number) => any; style: () => any }) => {
//
const { seriesIndex } = params;
//
const basicsCoord = api.coord([api.value(seriesIndex), api.value(1)]);
// y
const topBasicsYAxis = basicsCoord[1];
// x
const basicsXAxis = basicsCoord[0];
// y
const bottomYAxis = api.coord([api.value(seriesIndex), 0])[1];
return {
type: "group",
children: [
{
type: "leftShape",
shape: {
topBasicsYAxis,
basicsXAxis,
bottomYAxis,
},
style: {
fill: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: "rgba(0, 147, 221, 1)" },
{ offset: 1, color: "rgba(0, 88, 255, 0.20)" },
]), //
},
},
{
type: "rightShape",
shape: {
topBasicsYAxis,
basicsXAxis,
bottomYAxis,
},
style: {
fill: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: "rgba(0, 147, 221, 1)" },
{ offset: 1, color: "rgba(0, 88, 255, 0.20)" },
]), //
},
},
{
type: "topShape",
shape: {
topBasicsYAxis,
basicsXAxis,
bottomYAxis,
},
style: {
fill: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: "rgba(143, 231, 255, 1)" },
{ offset: 1, color: "rgba(0, 132, 255, 1)" },
]), //
},
},
{
type: "middleShape",
shape: {
topBasicsYAxis,
basicsXAxis,
bottomYAxis,
},
style: {
fill: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: "rgba(143, 231, 255, 1)" },
{ offset: 1, color: "rgba(0, 132, 255, 0)" },
]), //
},
},
],
};
};
const chartDom = ref(null);
let myChart: echarts.ECharts | null = null;
const initChart = () => {
if (chartDom.value) {
myChart = echarts.init(chartDom.value);
//
const WIDTH = 10;
//
const OBLIQUE_ANGLE_HEIGHT = 3.5;
const leftShape = echarts.graphic.extendShape({
buildPath(ctx, shape) {
const { topBasicsYAxis, bottomYAxis, basicsXAxis } = shape;
const p1 = [basicsXAxis - WIDTH, topBasicsYAxis - OBLIQUE_ANGLE_HEIGHT];
const p2 = [basicsXAxis - WIDTH, bottomYAxis];
const p3 = [basicsXAxis, bottomYAxis];
const p4 = [basicsXAxis, topBasicsYAxis];
ctx.moveTo(p1[0], p1[1]);
ctx.lineTo(p2[0], p2[1]);
ctx.lineTo(p3[0], p3[1]);
ctx.lineTo(p4[0], p4[1]);
},
});
const rightShape = echarts.graphic.extendShape({
buildPath(ctx, shape) {
const { topBasicsYAxis, bottomYAxis, basicsXAxis } = shape;
const p1 = [basicsXAxis, topBasicsYAxis];
const p2 = [basicsXAxis, bottomYAxis];
const p3 = [basicsXAxis + WIDTH, bottomYAxis];
const p4 = [basicsXAxis + WIDTH, topBasicsYAxis - OBLIQUE_ANGLE_HEIGHT];
ctx.moveTo(p1[0], p1[1]);
ctx.lineTo(p2[0], p2[1]);
ctx.lineTo(p3[0], p3[1]);
ctx.lineTo(p4[0], p4[1]);
},
});
const topShape = echarts.graphic.extendShape({
buildPath(ctx, shape) {
const { topBasicsYAxis, basicsXAxis } = shape;
const p1 = [basicsXAxis, topBasicsYAxis];
const p2 = [basicsXAxis + WIDTH, topBasicsYAxis - OBLIQUE_ANGLE_HEIGHT];
const p3 = [basicsXAxis, topBasicsYAxis - OBLIQUE_ANGLE_HEIGHT * 2];
const p4 = [basicsXAxis - WIDTH, topBasicsYAxis - OBLIQUE_ANGLE_HEIGHT];
ctx.moveTo(p1[0], p1[1]);
ctx.lineTo(p2[0], p2[1]);
ctx.lineTo(p3[0], p3[1]);
ctx.lineTo(p4[0], p4[1]);
},
});
const middleShape = echarts.graphic.extendShape({
buildPath(ctx, shape) {
const { topBasicsYAxis, basicsXAxis, bottomYAxis } = shape;
const p1 = [basicsXAxis - 0.5, topBasicsYAxis];
const p2 = [basicsXAxis - 0.5, bottomYAxis];
const p3 = [basicsXAxis + 0.5, bottomYAxis];
const p4 = [basicsXAxis + 0.5, topBasicsYAxis];
ctx.moveTo(p1[0], p1[1]);
ctx.lineTo(p2[0], p2[1]);
ctx.lineTo(p3[0], p3[1]);
ctx.lineTo(p4[0], p4[1]);
},
});
echarts.graphic.registerShape("leftShape", leftShape);
echarts.graphic.registerShape("rightShape", rightShape);
echarts.graphic.registerShape("topShape", topShape);
echarts.graphic.registerShape("middleShape", middleShape);
const options = {
grid: {
top: "12%",
left: "5%",
right: "3%",
bottom: "15%",
},
xAxis: {
type: "category",
data: [1, 2, 3, 4, 5],
axisLabel: {
formatter: (value: any) => value,
color: "#C0EEFF",
fontSize: 14,
},
nameTextStyle: {
color: "#243174",
},
axisLine: {
lineStyle: {
color: "#243174",
},
},
},
yAxis: {
name: "人数",
nameLocation: "end",
data: [100, 200, 300, 400],
nameTextStyle: {
color: "#C0EEFF",
fontSize: 14,
padding: [0, 5, 0, 0],
align: "right",
},
type: "value",
min: 0,
max: 500,
interval: 100,
axisLabel: {
color: "#C0EEFF",
fontSize: 14,
},
axisLine: {
show: true,
lineStyle: {
color: "#243174",
},
},
splitLine: {
lineStyle: {
type: "dashed",
color: "#308EFF",
width: 1,
opacity: 0.2,
},
},
},
series: [
{
type: "custom",
renderItem: renderItem,
color: "blue",
data: [100, 200, 300, 400],
},
{
type: "bar",
label: {
show: true,
position: "top",
fontSize: 12,
color: "rgba(192, 238, 255, 1)",
},
tooltip: {
show: false,
},
itemStyle: {
color: "transparent",
},
data: [100, 200, 300, 400],
},
],
};
myChart.setOption(options);
window.addEventListener("resize", handleResize);
}
};
const handleResize = () => {
myChart?.resize();
};
onMounted(() => {
initChart();
});
onUnmounted(() => {
window.removeEventListener("resize", handleResize);
myChart?.dispose();
});
</script>
<style lang="scss"></style>

View File

@ -0,0 +1,595 @@
<template>
<div ref="chartDom" class="w-full h-full"></div>
</template>
<script setup lang="ts">
import { onMounted, ref } from "vue";
import * as echarts from "echarts";
const chartDom = ref(null);
let myChart: echarts.ECharts | null = null;
//
const chartData = ref({
dates: ["5.24", "5.25", "5.26", "5.27", "5.28", "5.29", "5.30"],
seriesData: [
{ name: "获客", data: [180, 230, 200, 280, 250, 300, 350], color: "#20E6A4" },
{ name: "缴费", data: [150, 210, 180, 240, 200, 260, 320], color: "#0783FA" },
{ name: "流失", data: [120, 380, 220, 350, 300, 280, 400], color: "#FFD15C" },
],
});
const currentMode = ref("week");
const legendIcons = ref<{ [key: string]: string }>({});
// SVG
const generateSvgIcon = (color: string) => {
return encodeURIComponent(`
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" viewBox="0 0 16 16">
<g><g><path d="M0,2L0,14C0,15.1046,0.89543,16,2,16L14,16C15.1046,16,16,15.1046,16,14L16,2C16,0.89543,15.1046,0,14,0L2,0C0.89543,0,0,0.89543,0,2ZM13.949,6.32574L7.64171,11.99Q7.35295,12.25,6.94914,12.25Q6.54551,12.25,6.25625,11.9902L2.05119,8.2139Q1.75,7.94411,1.75,7.55595Q1.75,7.16798,2.05072,6.89792Q2.33947,6.63794,2.74329,6.63794Q3.14692,6.63794,3.43617,6.89771L6.94886,10.0523L12.5636,5.00998Q12.8523,4.75,13.2562,4.75Q13.6598,4.75,13.9488,5.00955Q14.25,5.27935,14.25,5.66751Q14.25,6.05547,13.949,6.32574Z" fill-rule="evenodd" fill="${color}" fill-opacity="1"/></g></g></svg>`);
};
//
const initLegendIcons = () => {
chartData.value.seriesData.forEach((item) => {
legendIcons.value[item.name] = generateSvgIcon(item.color);
});
};
//
const getLegendIcon = (name: string, isSelected = true) => {
const seriesItem = chartData.value.seriesData.find((item) => item.name === name);
const color = isSelected ? seriesItem?.color || "#555" : "#555";
return `image://data:image/svg+xml;charset=utf-8,${generateSvgIcon(color)}`;
};
//
const updateLegendIcons = (selected: Record<string, boolean>) => {
if (!myChart) return;
const option = myChart.getOption() as any;
const legendData = option.legend[0].data as any[];
//
const updatedLegendData = legendData.map((item: any) => {
const isSelected = selected[item.name] !== false;
return {
...item,
icon: getLegendIcon(item.name, isSelected),
};
});
//
myChart.setOption({
legend: {
data: updatedLegendData,
},
});
};
//
const generateSeries = (seriesData: any) => {
return seriesData.map((item: any,) => {
const series = {
name: item.name,
type: "line",
data: item.data,
symbol: "circle",
symbolSize: 8,
itemStyle: {
color: "#111", //
borderColor: item.color, //
borderWidth: 2,
},
lineStyle: {
width: 3,
color: item.color,
},
};
return series;
});
};
// /
const switchDisplayMode = (mode: string) => {
currentMode.value = mode;
//
if (mode === "week") {
// ()
chartData.value.dates = ["5.24", "5.25", "5.26", "5.27", "5.28", "5.29", "5.30"];
} else {
//
chartData.value.dates = ["1月", "2月", "3月", "4月", "5月", "6月", "7月"];
}
//
initChart();
};
const initChart = () => {
if (!myChart) {
myChart = echarts.init(chartDom.value);
}
//
initLegendIcons();
// SVG - 使Base64
const buttonSvgBase64 = encodeURIComponent(`
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="72" height="28" viewBox="0 0 72 28"><defs><filter id="master_svg0_104_04023" filterUnits="objectBoundingBox" color-interpolation-filters="sRGB" x="0" y="0" width="1" height="1"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/><feColorMatrix in="SourceAlpha" type="matrix" result="hardAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/><feOffset dy="8" dx="0"/><feGaussianBlur stdDeviation="6"/><feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/><feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0.08237092196941376 0 0 0 0 0.17847032845020294 0 0 0 1 0"/><feBlend mode="normal" in2="shape" result="effect1_innerShadow"/><feColorMatrix in="SourceAlpha" type="matrix" result="hardAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/><feOffset dy="-8" dx="0"/><feGaussianBlur stdDeviation="6"/><feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/><feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0.08235294371843338 0 0 0 0 0.18039216101169586 0 0 0 1 0"/><feBlend mode="normal" in2="effect1_innerShadow" result="effect2_innerShadow"/></filter></defs><g><g filter="url(#master_svg0_104_04023)"><path d="M0,14.5113C0,8.31958,0,6.07937,0.871948,4.36808C1.63894,2.86278,2.86278,1.63893,4.36808,0.871948C6.07937,0,8.31958,0,14.5113,0L72,0L72,13.4887C72,19.6804,72,21.9206,71.1281,23.6319C70.3611,25.1372,69.1372,26.3611,67.6319,27.1281C65.9206,28,63.6804,28,57.4887,28L0,28L0,14.5113Z" fill="#061E3A" fill-opacity="1"/></g><g><path d="M0,14.5113C0,8.31958,0,6.07937,0.871948,4.36808C1.63894,2.86278,2.86278,1.63893,4.36808,0.871948C6.07937,0,8.31958,0,14.5113,0L72,0L72,13.4887C72,19.6804,72,21.9206,71.1281,23.6319C70.3611,25.1372,69.1372,26.3611,67.6319,27.1281C65.9206,28,63.6804,28,57.4887,28L0,28L0,14.5113ZM14.5113,1L71,1L71,13.4887Q71,18.6574,70.8935,20.1702Q70.753,22.1653,70.237,23.1779Q69.2045,25.2045,67.1779,26.237Q66.1653,26.753,64.1702,26.8935Q62.6574,27,57.4887,27L1,27L1,14.5113Q1,9.34262,1.10652,7.82977Q1.247,5.83468,1.76295,4.82207Q2.79553,2.79553,4.82207,1.76295Q5.83468,1.247,7.82977,1.10652Q9.34262,1,14.5113,1Z" fill-rule="evenodd" fill="#2A8EFE" fill-opacity="1"/></g></g></svg>
`);
// SVG
const activeButtonSvgBase64 = encodeURIComponent(`
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="72" height="28" viewBox="0 0 72 28"><defs><radialGradient cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" id="master_svg0_85_00187" gradientTransform="translate(36 28) rotate(90) scale(16.125258922576904 182.11454980862436)"><stop offset="0%" stop-color="#FFCE4F" stop-opacity="0.5749016404151917"/><stop offset="99.90439414978027%" stop-color="#E0BF00" stop-opacity="0"/></radialGradient><linearGradient x1="0.5" y1="0" x2="0.5" y2="1" id="master_svg1_85_00188"><stop offset="0%" stop-color="#E0BF00" stop-opacity="0.4000000059604645"/><stop offset="100%" stop-color="#E0BF00" stop-opacity="0"/></linearGradient><linearGradient x1="0.5" y1="1" x2="0.5" y2="1.9133386611938477" id="master_svg2_85_00190"><stop offset="0%" stop-color="#FFF7A6" stop-opacity="1"/><stop offset="100%" stop-color="#046172" stop-opacity="0"/></linearGradient></defs><g><g><path d="M0,14.5113C0,8.31958,0,6.07937,0.871948,4.36808C1.63894,2.86278,2.86278,1.63893,4.36808,0.871948C6.07937,0,8.31958,0,14.5113,0L72,0L72,13.4887C72,19.6804,72,21.9206,71.1281,23.6319C70.3611,25.1372,69.1372,26.3611,67.6319,27.1281C65.9206,28,63.6804,28,57.4887,28L0,28L0,14.5113Z" fill="url(#master_svg0_85_00187)" fill-opacity="1"/><path d="M0,14.5113C0,8.31958,0,6.07937,0.871948,4.36808C1.63894,2.86278,2.86278,1.63893,4.36808,0.871948C6.07937,0,8.31958,0,14.5113,0L72,0L72,13.4887C72,19.6804,72,21.9206,71.1281,23.6319C70.3611,25.1372,69.1372,26.3611,67.6319,27.1281C65.9206,28,63.6804,28,57.4887,28L0,28L0,14.5113Z" fill="url(#master_svg1_85_00188)" fill-opacity="1"/></g><g><path d="M0,14.5113C0,8.31958,0,6.07937,0.871948,4.36808C1.63894,2.86278,2.86278,1.63893,4.36808,0.871948C6.07937,0,8.31958,0,14.5113,0L72,0L72,13.4887C72,19.6804,72,21.9206,71.1281,23.6319C70.3611,25.1372,69.1372,26.3611,67.6319,27.1281C65.9206,28,63.6804,28,57.4887,28L0,28L0,14.5113ZM14.5113,1L71,1L71,13.4887Q71,18.6574,70.8935,20.1702Q70.753,22.1653,70.237,23.1779Q69.2045,25.2045,67.1779,26.237Q66.1653,26.753,64.1702,26.8935Q62.6574,27,57.4887,27L1,27L1,14.5113Q1,9.34262,1.10652,7.82977Q1.247,5.83468,1.76295,4.82207Q2.79553,2.79553,4.82207,1.76295Q5.83468,1.247,7.82977,1.10652Q9.34262,1,14.5113,1Z" fill-rule="evenodd" fill="url(#master_svg2_85_00190)" fill-opacity="1"/></g></g></svg>
`);
const option = {
grid: {
top: "14%",
left: "5%",
right: "3%",
bottom: "15%",
},
legend: {
type: "plain",
itemWidth: 16,
itemHeight: 16,
top: 3,
left: "center",
itemGap: 40,
textStyle: {
color: "#C0EEFF",
fontSize: 14,
lineHeight: 16,
},
data: chartData.value.seriesData.map((item) => ({
name: item.name,
icon:
"image://data:image/svg+xml;charset=utf-8," +
encodeURIComponent(`
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" viewBox="0 0 16 16">
<g><g><path d="M0,2L0,14C0,15.1046,0.89543,16,2,16L14,16C15.1046,16,16,15.1046,16,14L16,2C16,0.89543,15.1046,0,14,0L2,0C0.89543,0,0,0.89543,0,2ZM13.949,6.32574L7.64171,11.99Q7.35295,12.25,6.94914,12.25Q6.54551,12.25,6.25625,11.9902L2.05119,8.2139Q1.75,7.94411,1.75,7.55595Q1.75,7.16798,2.05072,6.89792Q2.33947,6.63794,2.74329,6.63794Q3.14692,6.63794,3.43617,6.89771L6.94886,10.0523L12.5636,5.00998Q12.8523,4.75,13.2562,4.75Q13.6598,4.75,13.9488,5.00955Q14.25,5.27935,14.25,5.66751Q14.25,6.05547,13.949,6.32574Z" fill-rule="evenodd" fill="${item.color}" fill-opacity="1"/></g></g></svg>`),
textStyle: {
color: "#C0EEFF",
verticalAlign: "middle",
},
})),
selectedMode: true,
inactiveColor: "#555",
itemStyle: {
borderWidth: 0,
},
},
// 使graphic
graphic: [
//
{
type: "group",
right: 97,
top: 0,
z: 100,
children: [
{
type: "image",
z: 100,
style: {
image: `data:image/svg+xml;charset=utf-8,${currentMode.value === "week" ? activeButtonSvgBase64 : buttonSvgBase64}`,
width: 72,
height: 28,
},
cursor: "pointer",
onclick: () => switchDisplayMode("week"),
},
{
type: "text",
z: 100,
style: {
text: "按周",
x: 36,
y: 14,
textAlign: "center",
textVerticalAlign: "middle",
fill: `${currentMode.value === "week" ? "#F8EA21" : "#DBF7FF"}`,
fontSize: 14,
},
cursor: "pointer",
onclick: () => switchDisplayMode("week"),
},
],
},
//
{
type: "group",
right: 15,
top: 0,
z: 100,
children: [
{
type: "image",
z: 100,
style: {
image: `data:image/svg+xml;charset=utf-8,${currentMode.value === "month" ? activeButtonSvgBase64 : buttonSvgBase64}`,
width: 72,
height: 28,
},
cursor: "pointer",
onclick: () => switchDisplayMode("month"),
},
{
type: "text",
z: 100,
style: {
text: "按月",
x: 36,
y: 14,
textAlign: "center",
textVerticalAlign: "middle",
fill: `${currentMode.value === "month" ? "#F8EA21" : "#DBF7FF"}`,
fontSize: 14,
},
cursor: "pointer",
onclick: () => switchDisplayMode("month"),
},
],
},
],
tooltip: {
trigger: "axis",
renderMode: "html",
padding: 0,
borderWidth: 0,
extraCssText: "background-color: transparent;",
formatter: (params: any) => {
const date = params[0].name;
const seriesData = params
.map(
(item: any) => `<div class="tip-content">
<div class="tip-content-left">
<div class="tip-icon" style="background-color: ${item.borderColor};"></div>
<div class="tip-text">${item.seriesName}</div>
</div>
<div class="tip-content-right">
<div class="tip-text">${item.value}</div>
</div>
</div>`,
)
.join("");
return `<div style="" class='tool-tip-wrapper'>
<div class="tool-tip-header">
<span class="tip-date">${date}</span>
<div class="tip-graphic">
<div class="qua-group">
<div class="qua-item"></div>
<div class="qua-item"></div>
<div class="qua-item"></div>
<div class="qua-item"></div>
<div class="qua-item"></div>
</div>
<div class="rect-group">
<div class="rect-item"></div>
<div class="rect-item"></div>
<div class="rect-item"></div>
</div>
</div>
</div>
<div class="tip-content-wrapper">
${seriesData}
</div>
</div>`;
},
axisPointer: {
id: "xPointer",
type: "line", // 线
lineStyle: {
color: "#4760FF",
width: 2,
type: "dashed",
},
},
},
xAxis: {
type: "category",
data: chartData.value.dates,
axisLabel: {
formatter: (value: any) => value,
color: "#C0EEFF",
fontSize: 14,
},
nameTextStyle: {
color: "#243174",
},
axisLine: {
lineStyle: {
color: "#243174",
},
},
},
yAxis: {
name: "人数",
nameLocation: "end",
nameTextStyle: {
color: "#C0EEFF",
fontSize: 14,
padding: [0, 5, 0, 0],
align: "right",
},
type: "value",
min: 0,
max: 500,
interval: 100,
axisLabel: {
color: "#C0EEFF",
fontSize: 14,
},
axisLine: {
show: true,
lineStyle: {
color: "#243174",
},
},
splitLine: {
lineStyle: {
type: "dashed",
color: "#308EFF",
width: 1,
opacity: 0.2,
},
},
},
series: [
...generateSeries(chartData.value.seriesData),
{
type: "bar",
id: "axisOverlayBar",
zlevel: 1,
silent: false,
barWidth: "100%",
data: chartData.value.dates.map(() => 500), // 使y
itemStyle: {
color: "transparent",
},
tooltip: {
show: false
}
}
],
};
myChart.setOption(option, true);
//
const hoverBarId = 'mouseHoverBar';
myChart.on("mouseover", { seriesId: "axisOverlayBar" }, (params) => {
if (!myChart) return;
//
const dataIndex = params.dataIndex;
// option
const _option = myChart.getOption() as any;
//
let seriesIndex = -1;
if (_option.series && Array.isArray(_option.series)) {
_option.series.forEach((series: any, index: number) => {
if (series.id === hoverBarId) {
seriesIndex = index;
}
});
}
//
const hoverBarOption = {
id: hoverBarId,
type: 'bar',
barWidth: 40,
barGap: '-100%',
zlevel: 10,
silent: true,
animation: true,
data: chartData.value.dates.map((_: any, index: number) => {
return index === dataIndex ? 500 : '-'
}),
itemStyle: {
color: {
type: 'linear',
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [
{
offset: 0,
color: '#fff' //
},
{
offset: 1,
color: '#0783FA' //
}
],
global: false
},
opacity: 0.3,
},
tooltip: {
show: false
}
};
if (seriesIndex === -1) {
//
if (_option.series && Array.isArray(_option.series)) {
_option.series.push(hoverBarOption);
}
} else {
//
if (_option.series && Array.isArray(_option.series)) {
_option.series[seriesIndex].data = hoverBarOption.data;
}
}
//
myChart.setOption(_option, false);
});
//
myChart.on("mouseout", { seriesId: "axisOverlayBar" }, () => {
if (!myChart) return;
const _option = myChart.getOption() as any;
const hoverBarExists = _option.series.find((series: any) => series.id && series.id === hoverBarId);
if (hoverBarExists) {
try {
// series
if (_option.series && Array.isArray(_option.series)) {
//
const newSeries = _option.series.filter((series: any) => {
return series.id !== hoverBarId;
});
// series
_option.series = newSeries;
//
myChart.setOption(_option, true);
}
} catch (err) {
console.error("删除高亮条出错:", err);
}
}
});
myChart.on("legendselectchanged", (params: any) => {
//
updateLegendIcons(params.selected);
});
};
onMounted(() => {
initChart();
window.addEventListener("resize", () => myChart?.resize());
});
</script>
<style lang="scss" scoped>
:deep(.tool-tip-wrapper) {
background-color: transparent;
position: relative;
width: 184px;
border-radius: 4px;
box-shadow: 0px 4px 10px 0px #0d3472;
overflow: hidden;
padding: 10px;
background-color: rgb(3, 33, 64);
&::before {
content: "";
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
border: 2px solid transparent;
border-image: linear-gradient(rgb(3, 33, 64), rgba(0, 170, 255, 0.3)) 2;
}
.tool-tip-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 10px;
.tip-date {
font-size: 14px;
color: #c0eeff;
font-weight: 600;
}
.tip-graphic {
display: flex;
align-items: center;
.qua-group {
display: flex;
align-items: center;
margin-right: 4px;
.qua-item {
width: 2px;
height: 8px;
color: rgba(255, 255, 255, 1);
text-align: center;
transform: skewX(-40deg);
background: linear-gradient(360deg, #0085ff 0%, rgba(0, 133, 255, 0) 93%, rgba(0, 133, 255, 0) 100%);
margin-left: 3px;
}
}
.rect-group {
display: flex;
align-items: center;
.rect-item {
width: 5px;
height: 5px;
background-color: #00c2ff;
transform: rotate(45deg);
margin-left: 5px;
animation: colorChange 1.5s infinite;
&:nth-child(1) {
animation-delay: 0s;
}
&:nth-child(2) {
animation-delay: 0.5s;
}
&:nth-child(3) {
animation-delay: 1s;
}
}
}
}
}
.tip-content {
padding: 6px 7px 6px 10px;
border-radius: 4px;
display: flex;
align-items: center;
justify-content: space-between;
background-color: rgb(4, 50, 89);
font-size: 14px;
color: #b9ddfd;
.tip-content-left {
display: flex;
align-items: center;
.tip-icon {
width: 8px;
height: 8px;
border-radius: 50%;
margin-right: 5px;
}
}
}
.tip-content-wrapper {
display: grid;
grid-template-columns: 1fr;
gap: 4px;
}
}
@keyframes colorChange {
0%,
100% {
background-color: #00c2ff;
}
50% {
background-color: #0085ff;
}
}
</style>

View File

@ -52,7 +52,8 @@ const initChart = () => {
color: '#fff',
fontSize: 10
},
formatter: '{b}: {d}%'
formatter: '{b}: {d}%',
},
series: [
{

View File

@ -0,0 +1,125 @@
<template>
<div ref="chartRef" class="chart-container"></div>
</template>
<script lang="ts" setup>
import * as echarts from "echarts/core";
import { LineChart } from "echarts/charts";
import {
TitleComponent,
TooltipComponent,
GridComponent,
LegendComponent
} from "echarts/components";
import { CanvasRenderer } from "echarts/renderers";
echarts.use([
TitleComponent,
TooltipComponent,
GridComponent,
LegendComponent,
LineChart,
CanvasRenderer
]);
const chartRef = useTemplateRef("chartRef")
let chart: echarts.ECharts | null = null;
const initChart = () => {
if(!chartRef.value) return;
chart = echarts.init(chartRef.value)
const options = {
tooltip: {
trigger: 'axis'
},
grid: {
top:"3%",
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true
},
xAxis: {
type: 'category',
boundaryGap: false,
data: ['周一', '周二', '周三', '周四', '周五', '周六', '周日'],
axisLine: {
show: false
},
axisTick: {
show: false
},
axisLabel: {
show: false
}
},
yAxis: {
type: 'value',
axisLine: {
show: false
},
axisTick: {
show: false
},
axisLabel: {
show: false
},
splitLine: {
show: false
}
},
series: [
{
name: '数据1',
type: 'line',
smooth: true,
data: [120, 132, 101, 134, 90, 230, 210],
lineStyle: {
color: 'rgba(41, 241, 250, 1)',
width: 2
},
itemStyle: {
color: 'rgba(41, 241, 250, 1)',
},
symbol:"none",
areaStyle: {
opacity: 0.3,
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{
offset: 0,
color: 'rgb(9, 86, 128)'
},
{
offset: 1,
color: 'rgb(6, 37, 99)'
}
])
}
},
]
};
chart.setOption(options);
}
onMounted(() => {
initChart();
window.addEventListener('resize', () => {
chart?.resize();
});
});
onUnmounted(() => {
chart?.dispose();
window.removeEventListener('resize', () => {
chart?.resize();
});
});
</script>
<style scoped>
.chart-container {
width: 100%;
height: 400px;
}
</style>

View File

@ -0,0 +1,429 @@
<template>
<div class="flex flex-col">
<div class="relative flex-1">
<div ref="chartRef" class="w-full h-full"></div>
<div
class="absolute left-50% top-50% transform-translate-x-[-50%] transform-translate-y-[-50%] bg-gradient-to-b from-[#8FC8FF] to-white bg-clip-text text-transparent flex items-end leading-[1] z-[2]">
<span class="text-[24px] font-700">{{ total }}</span>
<span class="text-[16px] font-700"></span>
</div>
</div>
</div>
</template>
<script lang="ts" setup>
import * as echarts from "echarts/core";
import { TooltipComponent } from "echarts/components";
import { CanvasRenderer } from "echarts/renderers";
import { SurfaceChart } from "echarts-gl/charts";
import { Grid3DComponent } from "echarts-gl/components";
import { ref, onMounted, watch } from "vue";
echarts.use([TooltipComponent, Grid3DComponent, SurfaceChart, CanvasRenderer]);
type DefaultProps = {
chartData: any;
ringSize: number;
};
const props = withDefaults(defineProps<DefaultProps>(), {
chartData: [
{ name: "线下", value: 310, itemStyle: { color: "rgba(147, 219, 255, 1)" } },
{ name: "线上", value: 335, itemStyle: { color: "rgb(79, 214, 169)" } },
],
ringSize: 1,
});
const chartRef = ref<HTMLElement | null>(null);
let chart: echarts.ECharts | null = null;
interface SeriesItem {
[key: string]: any;
}
// 3D
const getHeight3D = (series: any[], height: number) => {
series.sort((a, b) => {
return b.pieData.value - a.pieData.value;
});
return (height * 35) / series[0].pieData.value;
};
//
const getParametricEquation = (startRatio: number, endRatio: number, isSelected: boolean, isHovered: boolean, k: number, h: number) => {
const midRatio = (startRatio + endRatio) / 2;
const startRadian = startRatio * Math.PI * 2;
const endRadian = endRatio * Math.PI * 2;
const midRadian = midRatio * Math.PI * 2;
if (startRatio === 0 && endRatio === 1) {
isSelected = false;
}
k = typeof k !== "undefined" ? k : 1 / 3;
const offsetX = isSelected ? Math.cos(midRadian) * 0.1 : 0;
const offsetY = isSelected ? Math.sin(midRadian) * 0.1 : 0;
const hoverRate = isHovered ? 1.05 : 1;
return {
u: {
min: -Math.PI,
max: Math.PI * 3,
step: Math.PI / 32,
},
v: {
min: 0,
max: Math.PI * 2,
step: Math.PI / 20,
},
x: (u: number, v: number) => {
if (u < startRadian) {
return offsetX + Math.cos(startRadian) * (1 + Math.cos(v) * k) * hoverRate;
}
if (u > endRadian) {
return offsetX + Math.cos(endRadian) * (1 + Math.cos(v) * k) * hoverRate;
}
return offsetX + Math.cos(u) * (1 + Math.cos(v) * k) * hoverRate;
},
y: (u: number, v: number) => {
if (u < startRadian) {
return offsetY + Math.sin(startRadian) * (1 + Math.cos(v) * k) * hoverRate;
}
if (u > endRadian) {
return offsetY + Math.sin(endRadian) * (1 + Math.cos(v) * k) * hoverRate;
}
return offsetY + Math.sin(u) * (1 + Math.cos(v) * k) * hoverRate;
},
z: (u: number, v: number) => {
if (u < -Math.PI * 0.5) {
return Math.sin(u);
}
if (u > Math.PI * 2.5) {
return Math.sin(u) * h * 0.1;
}
return Math.sin(v) > 0 ? 1 * h * 0.1 : -1;
},
};
};
// 3D
const getPie3D = (pieData: any[], internalDiameterRatio: number): any => {
const series: SeriesItem[] = [];
let sumValue = 0;
let startValue = 0;
let endValue = 0;
const legendData: any[] = [];
const k = 1 - internalDiameterRatio;
pieData.sort((a, b) => b.value - a.value);
// series-surface
for (let i = 0; i < pieData.length; i++) {
sumValue += pieData[i].value;
const seriesItem: SeriesItem = {
name: pieData[i].name || `series${i}`,
type: "surface",
parametric: true,
wireframe: {
show: false,
},
pieData: pieData[i],
pieStatus: {
selected: false,
hovered: false,
k: k,
},
animation: true,
zlevel: 1,
};
if (pieData[i].itemStyle) {
seriesItem.itemStyle = {
color: pieData[i].itemStyle.color,
opacity: 0.6,
};
}
series.push(seriesItem);
}
//
for (let i = 0; i < series.length; i++) {
endValue = startValue + series[i].pieData.value;
series[i].pieData.startRatio = startValue / sumValue;
series[i].pieData.endRatio = endValue / sumValue;
series[i].parametricEquation = getParametricEquation(series[i].pieData.startRatio, series[i].pieData.endRatio, false, false, k, series[i].pieData.value);
startValue = endValue;
legendData.push(series[i].name);
}
const boxHeight = getHeight3D(series, 26);
return {
tooltip: {
formatter: (params: any) => {
if (params.seriesName !== "mouseoutSeries" && params.seriesName !== "pie2d") {
const bfb = ((series[params.seriesIndex].pieData.endRatio - series[params.seriesIndex].pieData.startRatio) * 100).toFixed(2);
return `${params.seriesName}<br/>${bfb}%`;
}
},
},
xAxis3D: {
min: -1,
max: 1,
},
yAxis3D: {
min: -1,
max: 1,
},
zAxis3D: {
min: -4,
max: 4,
},
grid3D: {
show: false,
boxHeight: boxHeight,
viewControl: {
alpha: 30,
distance: 160,
rotateSensitivity: 1,
zoomSensitivity: 1,
panSensitivity: 1,
autoRotate: false,
},
},
series: series,
graphic: [
{
id: "backgroundImg",
elements: [
{
type: "image",
left: "center",
top: "33%",
style: {
image: "/images/particleBase.png",
width: 254,
height: 106,
},
z: 0,
origin: [127, 53],
keyframeAnimation: [
{
duration: 1600,
loop: true,
keyframes: [
{
percent: 0,
scaleX: 1.1,
scaleY: 1.1,
},
{
percent: 0.3,
scaleX: 1,
scaleY: 1,
},
{
percent: 1,
scaleX: 1.1,
scaleY: 1.1,
},
],
},
],
},
],
},
],
};
};
//
const initChart = () => {
if (!chartRef.value) return;
chart = echarts.init(chartRef.value);
const option = getPie3D(props.chartData, props.ringSize);
option.series.push({
name: "pie2d",
type: "pie",
labelLine: {
length: 18,
length2: 18,
smooth: true,
minTurnAngle: 20,
},
label: {
show: true,
position: "outside",
color: "inherit",
rich: {
a: {
width: 5,
height: 5,
borderRadius: 50,
backgroundColor: "inherit",
},
b: {
fontSize: 12,
},
c: {
fontSize: 12,
},
},
formatter: "{a|} {b|{b}}{d|{d}}%",
},
startAngle: -30,
clockwise: false,
radius: ["30%", "60%"],
padAngle: 360,
center: ["50%", "50%"],
data: props.chartData,
itemStyle: {
opacity: 1,
borderWidth: 0,
},
z: 1,
});
chart.setOption(option);
bindEvents();
};
//
const bindEvents = () => {
if (!chart) return;
// let selectedIndex = "";
// let hoveredIndex = "";
// chart.on("click", (params: any) => {
// if (!chart) return;
// const option = chart.getOption() as any;
// const isSelected = !option.series[params.seriesIndex].pieStatus.selected;
// const isHovered = option.series[params.seriesIndex].pieStatus.hovered;
// const k = option.series[params.seriesIndex].pieStatus.k;
// const startRatio = option.series[params.seriesIndex].pieData.startRatio;
// const endRatio = option.series[params.seriesIndex].pieData.endRatio;
// if (selectedIndex !== "" && selectedIndex !== params.seriesIndex) {
// option.series[selectedIndex].parametricEquation = getParametricEquation(
// option.series[selectedIndex].pieData.startRatio,
// option.series[selectedIndex].pieData.endRatio,
// false,
// false,
// k,
// option.series[selectedIndex].pieData.value,
// );
// option.series[selectedIndex].pieStatus.selected = false;
// }
// option.series[params.seriesIndex].parametricEquation = getParametricEquation(
// startRatio,
// endRatio,
// isSelected,
// isHovered,
// k,
// option.series[params.seriesIndex].pieData.value,
// );
// option.series[params.seriesIndex].pieStatus.selected = isSelected;
// isSelected ? (selectedIndex = params.seriesIndex) : null;
// chart.setOption(option);
// });
//
// chart.on("mouseover", (params: any) => {
// if (!chart) return;
// const option = chart.getOption() as any;
// if (hoveredIndex === params.seriesIndex) return;
// if (hoveredIndex !== "") {
// const isSelected = option.series[hoveredIndex].pieStatus.selected;
// const isHovered = false;
// const k = option.series[hoveredIndex].pieStatus.k;
// const startRatio = option.series[hoveredIndex].pieData.startRatio;
// const endRatio = option.series[hoveredIndex].pieData.endRatio;
// option.series[hoveredIndex].parametricEquation = getParametricEquation(
// startRatio,
// endRatio,
// isSelected,
// isHovered,
// k,
// option.series[hoveredIndex].pieData.value,
// );
// option.series[hoveredIndex].pieStatus.hovered = isHovered;
// hoveredIndex = "";
// }
// if (params.seriesName !== "mouseoutSeries" && params.seriesName !== "pie2d") {
// const isSelected = option.series[params.seriesIndex].pieStatus.selected;
// const isHovered = true;
// const k = option.series[params.seriesIndex].pieStatus.k;
// const startRatio = option.series[params.seriesIndex].pieData.startRatio;
// const endRatio = option.series[params.seriesIndex].pieData.endRatio;
// option.series[params.seriesIndex].parametricEquation = getParametricEquation(
// startRatio,
// endRatio,
// isSelected,
// isHovered,
// k,
// option.series[params.seriesIndex].pieData.value + 5,
// );
// option.series[params.seriesIndex].pieStatus.hovered = isHovered;
// hoveredIndex = params.seriesIndex;
// }
// chart.setOption(option);
// });
// //
// chart.on("globalout", () => {
// if (!chart) return;
// const option = chart.getOption() as any;
// if (hoveredIndex !== "") {
// const isSelected = option.series[hoveredIndex].pieStatus.selected;
// const isHovered = false;
// const k = option.series[hoveredIndex].pieStatus.k;
// const startRatio = option.series[hoveredIndex].pieData.startRatio;
// const endRatio = option.series[hoveredIndex].pieData.endRatio;
// option.series[hoveredIndex].parametricEquation = getParametricEquation(
// startRatio,
// endRatio,
// isSelected,
// isHovered,
// k,
// option.series[hoveredIndex].pieData.value,
// );
// option.series[hoveredIndex].pieStatus.hovered = isHovered;
// hoveredIndex = "";
// }
// chart.setOption(option);
// });
};
const total = computed(() => props.chartData.reduce((sum: number, item: any) => sum + item.value, 0));
//
watch(
() => props.chartData,
() => {
initChart();
},
{ deep: true },
);
//
onMounted(() => {
initChart();
});
</script>
<style scoped></style>

View File

@ -1,5 +1,5 @@
<template>
<div class="main-bg aspect-[16/9]">
<div class="main-bg flex flex-col scrollbar-hide h-screen overflow-auto ">
<header class="relative flex items-center">
<SvgComponent :content="headerSvg" class="w-full h-[98px]" />
<SvgComponent :content="titleSvg" class="w-[50%] h-[69px] absolute top-0 left-50% translate-x-[-50%]" />
@ -8,16 +8,32 @@
<DigitalWatch class="ml-[10px]" />
</div>
</header>
<div class="flex items-center justify-end pr-[24px] cursor-pointer">
<div class="flex items-center justify-end pr-[24px] cursor-pointer mb-[13px]">
<SvgIcon name="circle" class="text-[14px] text-[#C0EEFF] hover:rotate-90 transition-all duration-300" />
<div class="text-[#C0EEFF] text-[12px] ml-[5px]">数据更新时间:6.12 12:00:00</div>
</div>
<div class="flex items-center px-[24px]">
<PaymentTotal />
<TodayPayment class="ml-[20px]" />
<div class="grid grid-rows-[210px_358px_320px] gap-y-5 w-full min-h-[928px] gap-[20px] flex-1 overflow-auto mb-[27px]">
<div class="flex items-center px-[24px] justify-start">
<PaymentTotal />
<TodayPayment class="ml-[20px]" />
<GainTotal class="ml-[20px]" />
<GainToday class="ml-[20px]" />
<LossStatic class="ml-[20px]" />
</div>
<div class="flex items-center px-[24px] justify-start">
<OperatingTrends class=""/>
<AskSection class="ml-[20px]"/>
</div>
<div class="flex items-center px-[24px] overflow-x-auto">
<StudentSource />
<OnLineStatus class="ml-[20px]"/>
<OfflineStatus class="ml-[20px]" />
<SixStatistics class="ml-[20px]"/>
<ChargingRanking class="ml-[20px]" />
<WinCustomer class="ml-[20px]" />
</div>
</div>
<!-- <TDCharts :optionData="chartData" /> -->
</div>
</template>
@ -25,11 +41,20 @@
import SvgComponent from "@/components/SvgComponent.vue";
import SvgIcon from "@/components/svg-icon/SvgIcon.vue";
import TDCharts from "@/components/ease-charts/TDCharts.vue";
import DigitalWatch from "@/components/watch/DigitalWatch.vue";
import PaymentTotal from "@/views/components/PaymentTotal.vue";
import TodayPayment from "@/views/components/TodayPayment.vue";
import GainTotal from "@/views/components/GainTotal.vue";
import GainToday from "@/views/components/GainToday.vue";
import LossStatic from "@/views/components/LossStatic.vue";
import OperatingTrends from "@/views/components/OperatingTrends.vue";
import AskSection from "@/views/components/AskSection.vue";
import StudentSource from "@/views/components/StudentSource.vue";
import OnLineStatus from "@/views/components/OnlineStatus.vue";
import OfflineStatus from "@/views/components/OfflineStatus.vue";
import SixStatistics from "@/views/components/SixStatistics.vue";
import ChargingRanking from "./components/ChargingRanking.vue";
import WinCustomer from "./components/WinCustomer.vue";
import { useDate } from "@/composables/useDate";
@ -56,11 +81,7 @@
});
//
const chartData = ref([
{ name: "线上", value: 335, itemStyle: { color: "#d62728" } },
{ name: "线下", value: 310, itemStyle: { color: "#ffcc5c" } },
]);
</script>
<style scoped lang="scss">
@ -69,6 +90,7 @@
background-size: 100% 100%;
background-position: center;
background-repeat: no-repeat;
overflow-y: auto;
}
</style>

4
src/window-env.d.ts vendored
View File

@ -1,3 +1,5 @@
interface Window {
}
declare module 'echarts-gl/charts';
declare module 'echarts-gl/components';

View File

@ -1,5 +1,5 @@
import { defineConfig, presetIcons,presetUno } from "unocss";
import presetWind from "@unocss/preset-wind";
// import presetWind from "@unocss/preset-wind";
import { presetScrollbarHide } from 'unocss-preset-scrollbar-hide'
// import { presetPxToViewport } from "unocss-preset-px-to-vw-or-vh";
@ -12,7 +12,7 @@ export default defineConfig({
// keyToVw: ["font-size"],
// }),
presetUno(),
presetWind(),
// presetWind(),
presetScrollbarHide(),
presetIcons({
scale: 1,