Commit 900a8b1a authored by wuhao's avatar wuhao 🎯

kasdl

parents
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
node_modules
dist
dist-ssr
.history
*.local
# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
This diff is collapsed.
简体中文 | [繁體中文](./README.hk.md) | [English](./README.md)
<h1 align="center">
<b>TechUI-lite 开发包</b>
</h1>
<div align="center">TechUI-lite是一款免费简单易用的动态SVG可视化大屏开发框架,基于vite+vue3开发</div>
<p align="center">
<a href="https://lite.techui.net/docs">文档</a>
<a href="https://lite.techui.net/">演示站</a>
<a href="https://www.npmjs.com/package/techui-vue3-lite">核心库</a>
<a href="https://techui.net/docs">高级版</a>
<a href="https://t.me/ayin86cn">Telgram</a>
</p>
## 🛡️公告
**techUI-Lite框架完全免费,自由使用,其核心文件非开源,发布在NPM服务器**
**如果你发现这个框架对你有帮助,请给我一个star,我会更有动力开发更多的免费框架。我有非常多的不错的主意。**
**如果star数量达到500,我会把高级版的adaptivePanel下放到免费版。**
还有一款付费Premium版本,提供了更多的强大的功能,相关文档和Demo请访问这里 [TechUI-Premium](https://techui.net/docs)
注意:框架内的SVG素材、代码,仅限于框架内使用,请勿提取后用于其他用途。
**本开发包内置4个数据屏,如下图。**
**演示GIF动画**
<img src="./demoImage/techui-vue3-lite.gif" style="border-radius:10px" width="800" />
**数据屏A**
<img src="./demoImage/dashboardA-CN.png" style="border-radius:10px" width="800" />
**数据屏B**
<img src="./demoImage/dashboardB-CN.png" style="border-radius:10px" width="800" />
**数据屏C**
<img src="./demoImage/dashboardC-CN.png" style="border-radius:10px" width="800" />
**数据屏D**
<img src="./demoImage/dashboardD-CN.png" style="border-radius:10px" width="800" />
**更多Demo,请查阅 [TechUI-Lite-Demo](https://lite.techui.net/)**
-----
## ✨特性
- **🖥️全端适配**
完美的等比适配方案,个人电脑、手机、平板、企业拼接屏,可以说绝大多数终端设备均可以完美适配。
- **🛸自由开发无限制**
采用vite、vue3等流行技术栈,通过调用自研发组件和图表组件,不需要过多繁琐的开发过程即可快速部署上线,大大缩短了开发周期。真正做到了源码级的自由开发。
- **📊企业拼接屏**
面对企业级的拼接屏,我们有着非常多的展现方案,可以根据客户的拼接屏设备情况进行定制开发。在任意设备下均可以达到最佳的展现效果。
- **🧩去位图化全面使用动态SVG**
全面矢量化(去位图化),因可视化大屏的特殊使用场景,采用传统位图的情况图形放大细节模糊,而采用矢量图细节缩放后还能保持原来的细节清晰度。
- **🚀稳步迭代急速响应**
本框架历经多个版本迭代,bug修复及时,功能拓展稳步进行中,Lite版本和Premium同步更新。
- **🧑‍🚀完全免费,自由使用**
lite版本,完全免费,无任何使用限制,可用于任何类型的产品,项目等。
-----
## 📜更新说明
- **20230714 techui-vue3-lite-ver3.5 Lite正式版发布,其SVG元素节点计算采用WASM组件计算返回**
-----
## 📖安装教程
1. `cnpm i` 安装依赖,建议使用cnpm
2. `npm run dev` 启动项目即可预览
开发包介绍和使用方式请查阅 [文档](https://techui.net/docs)
-----
## 🛠️兼容性和Nodejs版本
1. nodejs 16-18 支持良好其他版本未测试
2. 除IE外的主流浏览器均支持良好,包括移动端浏览器。
-----
## 🌟合作洽谈
Lite版本框架免费使用,不提供任何技术支持,遇到问题请在github提交issues,或者添加以下QQ群进行技术交流。
数据可视化TechGroupQQ群:119059920 技术交流
或者添加 [TechUI discord](https://discord.gg/JXgn5Gq2)讨论群组。
或者添加 [TechUI Telgram](https://t.me/+RJZ4cmDrcCFmNWNl)讨论群组。
对于付费服务,如定制开发、技术支持,或购买高级许可证,请通过以下联系方式与我联系
微信:ayin86cn
<img src="./demoImage/QRcode.png" width="300" />
海外客户,请通过邮件联系 ayin86cn@gmail.com
也可以添加TechUI的Telgram讨论群组 [TechUI](https://t.me/+RJZ4cmDrcCFmNWNl)
-----
## ❤️我能提供的服务
作者本人,由UI设计师转为前端开发,从业15年之久,在一个项目或产品的开发中,可以承担的职责有:产品经理、UI设计师、前端开发。
所以,可以说是初创公司最佳且划算的合作伙伴,欢迎洽谈合作。
#### 可以具体做的工作
- UI设计图
- 产品、项目的规划和设计
- 可视化项目开发
- GEO项目开发(echarts+geojson+在线地图)
- Rust开发WASM模块
- 任意类型的业务系统
- 移动端开发
- 文档编撰
- 前端安全,加解密
[简体中文](./README.cn.md) | 繁體中文 | [English](./README.md)
<h1 align="center">
<b>TechUI-lite 開發包</b>
</h1>
<div align="center">TechUI-lite是一款免費簡單易用的動態SVG可視化大屏開發框架,基於vite+vue3開發</div>
<p align="center">
<a href="https://lite.techui.net/docs">文檔</a>
<a href="https://lite.techui.net/">演示站</a>
<a href="https://www.npmjs.com/package/techui-vue3-lite">核心庫</a>
<a href="https://techui.net/docs">高級版</a>
<a href="https://t.me/ayin86cn">Telgram</a>
</p>
## 🛡️公告
**techUI-Lite框架完全免費,自由使用,其核心文件非開源,發佈在NPM服務器**
**如果你發現這個框架對你有幫助,請給我一個star,我會更有動力開發更多的免費框架。我有非常多的不錯的主意。**
**如果star數量達到500,我會把高級版的adaptivePanel下放到免費版。**
還有一款付費Premium版本,提供了更多的強大的功能,相關文檔和Demo請訪問這裡 [TechUI-Premium](https://techui.net/docs)
注意:框架內的SVG素材、代碼,僅限於框架內使用,請勿提取後用於其他用途。
**本開發包內置4個數據屏,如下圖。**
**演示GIF動畫**
<img src="./demoImage/techui-vue3-lite.gif" style="border-radius:10px" width="800" />
**數據屏A**
<img src="./demoImage/dashboardA-HK.png" style="border-radius:10px" width="800" />
**數據屏B**
<img src="./demoImage/dashboardB-HK.png" style="border-radius:10px" width="800" />
**數據屏C**
<img src="./demoImage/dashboardC-HK.png" style="border-radius:10px" width="800" />
**數據屏D**
<img src="./demoImage/dashboardD-HK.png" style="border-radius:10px" width="800" />
**更多Demo,請查閱 [TechUI-Lite-Demo](https://lite.techui.net/)**
-----
## ✨特性
- **🖥️全端適配**
完美的等比適配方案,個人電腦、手機、平板、企業拼接屏,可以說絕大多數終端設備均可以完美適配。
- **🛸自由開發無限制**
採用vite、vue3等流行技術棧,通過調用自研發組件和圖表組件,不需要過多繁瑣的開發過程即可快速部署上線,大大縮短了開發週期。真正做到了源碼級的自由開發。
- **📊企業拼接屏**
面對企業級的拼接屏,我們有著非常多的展現方案,可以根據客戶的拼接屏設備情況進行定制開發。在任意設備下均可以達到最佳的展現效果。
- **🧩去位圖化全面使用動態SVG**
全面矢量化(去位圖化),因可視化大屏的特殊使用場景,採用傳統位圖的情況圖形放大細節模糊,而採用矢量圖細節縮放後還能保持原來的細節清晰度。
- **🚀穩步迭代急速響應**
本框架歷經多個版本迭代,bug修復及時,功能拓展穩步進行中,Lite版本和Premium同步更新。
- **🧑‍🚀完全免費,自由使用**
lite版本,完全免費,無任何使用限制,可用於任何類型的產品,項目等。
-----
## 📜更新說明
- **20230714 techui-vue3-lite-ver3.5 Lite正式版發布,其SVG元素節點計算採用WASM組件計算返回**
-----
## 📖安裝教程
1. `cnpm i` 安裝依賴
2. `npm run dev` 啟動項目即可預覽
開發包介紹和使用方式請查閱 [文檔](https://techui.net/docs)
-----
## 🛠️兼容性和Nodejs版本
1. nodejs 16-18 支持良好其他版本未測試
2. 除IE外的主流瀏覽器均支持良好,包括移動端瀏覽器。
-----
## 🌟合作洽談
Lite版本框架免費使用,不提供任何技術支持,遇到問題請在github提交issues。
或者添加 [TechUI discord](https://discord.gg/JXgn5Gq2)討論群組。
或者添加 [TechUI Telgram](https://t.me/+RJZ4cmDrcCFmNWNl)討論群組。
對於付費服務,如定制開發、技術支持,或購買高級許可證,請通過以下聯繫方式與我聯繫
WhatsApp 掃描下方二維碼。
<img src="./demoImage/WhatsApp.png" width="300" />
或者通過Telegram聯繫我 [@ayin86cn](https://t.me/ayin86cn)
您也可以通過電子郵件與我聯繫 ayin86cn@gmail.com 我將每1-3天檢查一次我的電子郵件
-----
## ❤️我能提供的服務
作者本人,由UI設計師轉為前端開發,從業15年之久,在一個項目或產品的開發中,可以承擔的職責有:產品經理、UI設計師、前端開發。
所以,可以說是初創公司最佳且划算的合作夥伴,歡迎洽談合作。希望能尋得一份穩定長期的遠程工作。
#### 可以具體做的工作
- UI設計圖
- 產品、項目的規劃和設計
- 可視化項目開發
- GEO項目開發(echarts+geojson+在線地圖)
- Rust開發WASM模塊
- 任意類型的業務系統
- 移動端開發
- 文檔編撰
- 前端安全,加解密
[简体中文](./README.cn.md) | [繁體中文](./README.hk.md) | English
<h1 align="center">
<b>TechUI-lite Development Kit</b>
</h1>
<div align="center">TechUI-lite is a free and easy to use Dynamic SVG Data Visualization Dashboard development tool, based on vite + vue3 development</div>
<p align="center">
<a href="https://lite.techui.net/docs">Documentation</a>
<a href="https://lite.techui.net/">Demo Site</a>
<a href="https://www.npmjs.com/package/techui-vue3-lite">Core library</a>
<a href="https://techui.net/docs">Premium</a>
<a href="https://t.me/ayin86cn">Telgram</a>
</p>
## 💖Need A Remote Job
**I am planning to quit my job and if anyone can offer a long term remote job, please contact me. All my skills and frameworks are free to use if a partnership is reached.**
-----
## 🛡️ Announcements
**techUI-Lite framework is completely free, free to use without restrictions, its core files are non-open source and published on NPM server**
**If you find this framework helpful to you, please give me a star, I will be more motivated to develop more free frameworks. I have so many great ideas.**
**If the number of stars reaches 500, I will transplant the premium version of adaptivePanel to the lite version.**
There is also a paid Premium version, which provides more powerful features, related documentation and demos please visit here [TechUI-Premium](https://techui.net/docs)
Note: The SVG material and code in the framework are limited to use in the framework, please do not extract them for other purposes.
**This development kit has 4 built-in data screens, as shown in the figure below.**
**Demo Gif animations**
<img src="./demoImage/techui-vue3-lite.gif" style="border-radius:10px" width="800" />
**Data Screen A**
<img src="./demoImage/dashboardA-EN.png" style="border-radius:10px" width="800" />
**Data Screen B**
<img src="./demoImage/dashboardB-EN.png" style="border-radius:10px" width="800" />
**Data Screen C**
<img src="./demoImage/dashboardC-EN.png" style="border-radius:10px" width="800" />
**Data Screen D**
<img src="./demoImage/dashboardD-EN.png" style="border-radius:10px" width="800" />
**For more demos, please refer to [TechUI-Lite-Demo](https://lite.techui.net/)**
-----
## ✨Features
- **🖥️Full port adaptation**
Perfect ratio adaptation solution, personal computer, mobile phone, tablet, enterprise splicing screen, it can be said that most terminal devices can be perfectly adapted.
- **🛸Free Development Unlimited**
Using popular technology stacks such as vite and vue3, by calling self-developed components and chart components, it can be quickly deployed and launched without too much tedious development process, which greatly shortens the development cycle. It has truly achieved free development at the source code level.
- **📊Enterprise Splicing Screen**
In the face of enterprise-level splicing screens, we have a lot of display solutions, which can be customized and developed according to the customer's splicing screen equipment. The best display effect can be achieved under any device.
- **🧩De-bitmapping full use of Dynamic SVG**
Comprehensive vectorization (de-bitmapping), due to the special use scene of large-screen visualization, the details of graphics are blurred when traditional bitmaps are used, but the original detail clarity can be maintained after zooming in on vector graphics.
- **🚀Stable iteration and rapid response**
This framework has gone through multiple version iterations, bug fixes are timely, function expansion is progressing steadily, and the Lite version and Premium are updated synchronously.
- **🧑‍🚀Completely free, use freely**
The lite version is completely free, without any usage restrictions, and can be used for any type of product, project etc.
-----
## 📜 Update Description
- **20230714 techui-vue3-lite-ver3.5 Lite is officially released, and its SVG element node calculation uses WASM component calculation to return**
-----
## 📖Installation Tutorial
1. `cnpm i` installs dependencies
2. `npm run dev` starts the project and you can preview it
For the introduction and usage of the development kit, please refer to [Documentation](https://techui.net/docs)
-----
## 🛠️ Compatibility and Nodejs Versions
1. nodejs 16-18 well supported other versions not tested
2. well supported by all major browsers except IE, including mobile browsers.
-----
## 🌟 Cooperation negotiation
The Lite version framework is free to use and does not provide any technical support. If you encounter any problems, please submit issues on github。
Or add [TechUI discord](https://discord.gg/JXgn5Gq2) to the discussion group.
Or add [TechUI Telgram](https://t.me/+RJZ4cmDrcCFmNWNl) to the discussion group.
For paid services, such as custom development, technical support, or purchasing a premium license, please contact me via the following contact information
WhatsApp scan the QR code below.
<img src="./demoImage/WhatsApp.png" width="300" />
Or contact me via Telegram [@ayin86cn](https://t.me/ayin86cn)
You can also contact me via email ayin86cn@gmail.com I will check my email every 1-3 days
-----
## ❤️ What I can offer
The author himself, a UI designer turned front-end developer, has been in the field for 15 years and can take on the responsibilities of product manager, UI designer and front-end developer in a project or product development.
Therefore, it can be said to be the best and cost-effective partner for a start-up company, welcome to discuss cooperation. I hope to find a stable and long-term remote job. Preferably a remote job in Canada, hope to have the opportunity to go to this country.
#### Specific tasks that can be done
- UI design
- Planning and design of products and projects
- Visualization project development
- GEO project development (echarts+geojson+online map)
- Rust development of WASM modules
- Any type of business system
- APP development
- Documentation compilation
- Front-end security, encryption and decryption
This diff is collapsed.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/logo.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" href="./static/lib/ayinfont/css/ayinfont.css">
<link rel="stylesheet" href="./static/lib/carbon/carbon.min.css">
<title>TechUI Vue3 lite</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.js"></script>
</body>
</html>
{
"name": "techui",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview"
},
"dependencies": {
"axios": "^1.4.0",
"ayin-color": "^1.0.9",
"ayin-lessmixins": "^1.0.7",
"echarts": "^5.4.2",
"element-plus": "^2.3.3",
"techui-vue3-lite": "^3.0.7",
"vue": "^3.2.47",
"vue-router": "^4.1.6",
"vuex": "^4.1.0"
},
"devDependencies": {
"@rollup/plugin-terser": "^0.4.3",
"@vitejs/plugin-vue": "^4.1.0",
"less": "^4.1.3",
"less-loader": "^11.1.0",
"vite": "^4.3.9"
}
}
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 27.2.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 200 200" style="enable-background:new 0 0 200 200;" xml:space="preserve">
<style type="text/css">
.st0{fill:#004EEA;}
.st1{fill:#0034B7;}
.st2{fill:#FFA522;}
.st3{fill:#FFB757;}
</style>
<g>
<g>
<polygon class="st0" points="189,99.7 144.2,99.7 86.3,5.6 131,5.6 "/>
<polygon class="st1" points="86.3,193.8 131,193.8 189,99.7 144.2,99.7 "/>
</g>
<g>
<polygon class="st2" points="11.6,99.7 56.3,99.7 90.8,50.8 46,50.8 "/>
<polygon class="st3" points="90.8,148.6 46,148.6 11.6,99.7 56.3,99.7 "/>
</g>
</g>
</svg>
/*A类字体 标题*/
@font-face { font-family: "cn0"; src:url(../webfonts/C-YS-BTTH.woff2) format("woff2"); font-style: normal; font-weight: 300; font-display: block; }/*优设标题黑*/
/*Eng常规*/
@font-face { font-family: "en0"; src:url(../webfonts/E-Vibrocentric.woff2) format("woff2"); font-style: normal; font-weight: 300; font-display: block; }
@font-face { font-family: "en1"; src:url(../webfonts/E-GeosansLight.woff2) format("woff2"); font-style: normal; font-weight: 300; font-display: block; }
@font-face { font-family: "en2"; src:url(../webfonts/E-digifacewide.woff2) format("woff2"); font-style: normal; font-weight: 300; font-display: block; }
@font-face { font-family: "en3"; src:url(../webfonts/E-SlicedJuice.woff2) format("woff2"); font-style: normal; font-weight: 300; font-display: block; }
@font-face { font-family: "en4"; src:url(../webfonts/E-Potra.woff2) format("woff2"); font-style: normal; font-weight: 300; font-display: block; }
@font-face { font-family: "en5"; src:url(../webfonts/E-V5ProphitCell.woff2) format("woff2"); font-style: normal; font-weight: 300; font-display: block; }
@font-face { font-family: "en6"; src:url(../webfonts/E-PROGBOT.woff2) format("woff2"); font-style: normal; font-weight: 300; font-display: block; }
@font-face { font-family: "en7"; src:url(../webfonts/E-BMPinholeA13.woff2) format("woff2"); font-style: normal; font-weight: 300; font-display: block; }
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
{
"icon":"path://m569.52,440.01c18.46,31.99-4.71,71.99-41.58,71.99H48.05c-36.94,0-60-40.05-41.58-71.99L246.42,23.99c18.47-32.01,64.72-31.95,83.15,0l239.94,416.03h0Zm-281.52-86.01c-25.4,0-46,20.6-46,46s20.6,46,46,46,46-20.6,46-46-20.6-46-46-46Zm-43.67-165.35l7.42,136c.35,6.36,5.61,11.35,11.98,11.35h48.55c6.37,0,11.64-4.98,11.98-11.35l7.42-136c.38-6.87-5.1-12.65-11.98-12.65h-63.38c-6.88,0-12.36,5.78-11.98,12.65h0Z"
}
\ No newline at end of file
This diff is collapsed.
{
"legend":["开发任务","采购任务","销售任务"],
"data":[45,33,77]
}
\ No newline at end of file
<script setup>
const store=useStore();
const router = useRouter();
const route = useRoute();
const { proxy } = getCtx();
// watch(()=>proxy.$tState.adaptiveConfig.chartCounter,(val,old)=>{
// // console.log("$tStateWatch",val);
// })
onMounted(()=>{
})
</script>
<template>
<div id="root-techui" :class="`root-BG lang-${store.state.lang}`" >
<router-view></router-view>
</div>
</template>
<style lang="less"></style>
import { http,fetchLocl} from "./request"
//接口demo
export const httpGetMap = (url,params) => { return fetchLocl("get",url+params)}
// export const loginApi = params => { return http("post",'/test/ste/', params)}
// export const httpGaugeTriple = params => { return http("get",'/static/tempData/gaugeTriple.json', params)}
import axios from 'axios'
const envMode=process.env.NODE_ENV;
const publicUrl=envMode=='development'?'/':"/api"
/**
* 封装请求
* @param:{method} String 请求类型,必填
* @param:{url} String 请求地址,必填
* @param:{params} Object 参数参数,非必填
* @returns:Promise {<pending>}
**/
export const http = (method, url, params = {},loading) => {
return new Promise(function(resolve, reject) {
axios({
method: method,
url: publicUrl+url,
headers: {
'Content-Type': 'application/json',
},
data: params,
})
.then(res => {
if(res.status==200){
// if(!res.data.success){
// // showMessage(res.data.errorMessage, "error")
// }else{
// }
resolve(res.data);
}else{
console.error('axiosThen',res)
reject(res);
}
})
.catch(err => {
console.error('axiosCatch',err);
reject(err);
// ElMessage({ message: "提交失败", showClose: true, center: true, duration: 2000, type:'error' });
// !loadingDisable&&hideLoading()
})
})
};
//封装fetch
export const fetchLocl = async(method, url, params)=>{
var opts = {
method,
// headers: {
// 'Accept': 'application/json',
// 'Content-Type': 'application/x-www-form-urlencoded',
// },
}
if(method=='post'){ opts.body={params} }
return await fetch(url,opts).then((res) => {
return res.json();
})
// .then((res) => { return res; })
// .catch((error) => { console.error(error) })
}
\ No newline at end of file
.lang-cn .system-name{.ff("cn0");}
.lang-hk .system-name{ font-size: 30px; font-weight: bold;}
.lang-en .system-name{.ff("en0"); font-size: 30px; font-weight: bold;}
\ No newline at end of file
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="37.07" height="36" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 198"><path fill="#41B883" d="M204.8 0H256L128 220.8L0 0h97.92L128 51.2L157.44 0h47.36Z"></path><path fill="#41B883" d="m0 0l128 220.8L256 0h-51.2L128 132.48L50.56 0H0Z"></path><path fill="#35495E" d="M50.56 0L128 133.12L204.8 0h-47.36L128 51.2L97.92 0H50.56Z"></path></svg>
\ No newline at end of file
<script setup>
const route = useRoute();
const router = useRouter();
const store = useStore();
const inited=ref(false)
const nav=[
{label:"Document",path:"http://lite.techui.net/docs"},
{label:"Gtihub",path:"https://github.com/ayin86/techui-vue3-lite"},
{label:"Premium",path:"http://techui.net/docs/"},
]
const langs=[
{label:"简中",value:"cn"},
{label:"繁中",value:"hk"},
{label:"English",value:"en"},
]
const goToLink=(item)=>{
window.open(item.path);
}
const changLang=(item)=>{
store.state.lang=item.value
if(item.value=='cn'){
router.push("/dashboardA-cn");
}else if(item.value=='hk'){
router.push("/dashboardA-hk");
}else if(item.value=='en'){
router.push("/dashboardA-en");
}
}
onMounted(() => {
inited.value=true
})
</script>
<template>
<div :class="`external-wrap ${inited&&'inited'}`" >
<div class="link-wrap">
<div class="item" @click="goToLink(item)" v-for="item in nav">
{{ item.label }}
</div>
</div>
<div class="lang-switch" >
<div :class="`item ${store.state.lang==item.value?'active':''}`" @click="changLang(item)" v-for="(item,index) in langs">{{item.label}}</div>
</div>
</div>
</template>
<style lang="less">
.external-wrap{.poa; left:40px; top:0; display:flex; z-index: 20;
.link-wrap{ display:flex;
.item{padding:10px; .fc(@bld6); .por; cursor: pointer; .ani;
&:hover{.fc(@cbl5);}
}
}
.lang-switch{ display:flex; .por; margin:0 0 0 10px;padding:0 0 0 10px;
&:before{content:""; .bdl(@bld6); .poa; left:0; top:10px; bottom:10px;}
.item{padding:10px; .fc(@bld6); .por; cursor: pointer; .ani;
&:before{.poa; top:0; left:50%; .bdr(0 0 10px 10px); .fixc("x"); width: 0%; opacity: 0; .ani; content:" "; height:5px; .bgc(@cbl6);}
&:hover{.fc(@cbl5);}
&.active{.fc(@cbl3);
&:before{ opacity: 1;}
}
}
}
&.inited{
.active{
&:before{width: 90%;}
}
}
}
</style>
\ No newline at end of file
<script setup>
const route = useRoute();
const router = useRouter();
const store = useStore();
const inited=ref(false)
const nav=[
{lang:"en",label:"DashboardA",path:"/dashboardA-en"},
{lang:"en",label:"DashboardB",path:"/dashboardB-en"},
{lang:"en",label:"DashboardC",path:"/dashboardC-en"},
{lang:"en",label:"DashboardD",path:"/dashboardD-en"},
{lang:"cn",label:"DashboardA",path:"/dashboardA-cn"},
{lang:"cn",label:"DashboardB",path:"/dashboardB-cn"},
{lang:"cn",label:"DashboardC",path:"/dashboardC-cn"},
{lang:"cn",label:"DashboardD",path:"/dashboardD-cn"},
{lang:"hk",label:"DashboardA",path:"/dashboardA-hk"},
{lang:"hk",label:"DashboardB",path:"/dashboardB-hk"},
{lang:"hk",label:"DashboardC",path:"/dashboardC-hk"},
{lang:"hk",label:"DashboardD",path:"/dashboardD-hk"},
]
const goToRouter=(item)=>{
router.push(item.path);
}
onMounted(() => {
inited.value=true
})
</script>
<template>
<div :class="`nav-wrap ${inited&&'inited'}`" >
<template v-for="item in nav">
<div v-if="item.lang==store.state.lang" :class="`item ${route.path==item.path?'active':''}`" @click="goToRouter(item)" >
{{ item.label }}
</div>
</template>
</div>
</template>
<style lang="less">
.nav-wrap{.poa; right:50px; top:0; display:flex; z-index: 20;
.item{padding:10px; .fc(@bld6); .por; cursor: pointer; .ani;
&:before{.poa; top:0; left:50%; .bdr(0 0 10px 10px); .fixc("x"); width: 0%; opacity: 0; .ani; content:" "; height:5px; .bgc(@cbl6);}
&:hover{.fc(@cbl5);}
&.active{.fc(@cbl3);
&:before{ opacity: 1;}
}
}
&.inited{
.active{
&:before{width: 90%;}
}
}
}
</style>
\ No newline at end of file
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import * as echarts from 'echarts';
window.echarts=echarts;
import techUILite from "techui-vue3-lite"
import vue3api from '@/plugins/vue3api'
import common from '@/plugins/common'
const app=createApp(App)
techUILite(app).then(()=>{
app.use(router)
app.use(store)
app.use(vue3api)
app.use(common)
app.mount('#app')
})
import "@/assets/less/main.less";
import axios from 'axios'
// import {AyinColor} from "ayin-color"
export default function(app){
window.axios=axios
// app.use(AyinColor)
// const comps=[ ];
// comps.forEach((com,a) => {
// let cona=com.name?com.name:com.__name
// app.component(cona,com);
// });
}
import { ref, reactive,toRefs,toRaw,h,computed,watch,shallowRef, getCurrentInstance,onMounted,onBeforeMount,onBeforeUnmount,onUnmounted,nextTick,defineEmits } from 'vue'
import { useRoute, useRouter ,onBeforeRouteUpdate } from "vue-router"
import { useStore, mapState, mapGetters, mapMutations, mapActions } from "vuex";
export default function(app){
//vue
window.ref = ref
window.reactive = reactive
window.toRefs = toRefs
window.toRaw = toRaw
window.h = h
window.computed = computed
window.watch = watch
window.shallowRef = shallowRef
window.getCurrentInstance=getCurrentInstance
window.getCtx=getCurrentInstance
window.onMounted=onMounted
window.onBeforeMount=onBeforeMount
window.onBeforeUnmount=onBeforeUnmount
window.onUnmounted=onUnmounted
window.nextTick=nextTick
window.defineEmits=defineEmits
//router
window.useRoute=useRoute
window.useRouter=useRouter
window.routeUpdate=onBeforeRouteUpdate
//vuex
window.useStore=useStore
window.mapState=mapState
window.mapGetters=mapGetters
window.mapMutations=mapMutations
window.mapActions=mapActions
}
import { createRouter, createWebHistory,createWebHashHistory,useRoute } from 'vue-router'
import{ defineAsyncComponent } from"vue"
import store from './store'
const router = createRouter({
// history: createWebHistory(),
history: createWebHashHistory(),
routes :[
{
path: "/",
name: "layout",
redirect:"/dashboardA-en",
},
{
path: "/dashboardA-en",
name: "dashboardA-en",
component:()=>import("@/viewsEN/dashboardA/dashboardA-index.vue"),
},
{
path: "/dashboardB-en",
name: "dashboardB-en",
component:()=>import("@/viewsEN/dashboardB/dashboardB-index.vue"),
},
{
path: "/dashboardC-en",
name: "dashboardC-en",
component:()=>import("@/viewsEN/dashboardC/dashboardC-index.vue"),
},
{
path: "/dashboardD-en",
name: "dashboardD-en",
component:()=>import("@/viewsEN/dashboardD/dashboardD-index.vue"),
},
{
path: "/dashboardA-cn",
name: "dashboardA-cn",
component:()=>import("@/viewsCN/dashboardA/dashboardA-index.vue"),
},
{
path: "/dashboardB-cn",
name: "dashboardB-cn",
component:()=>import("@/viewsCN/dashboardB/dashboardB-index.vue"),
},
{
path: "/dashboardC-cn",
name: "dashboardC-cn",
component:()=>import("@/viewsCN/dashboardC/dashboardC-index.vue"),
},
{
path: "/dashboardD-cn",
name: "dashboardD-cn",
component:()=>import("@/viewsCN/dashboardD/dashboardD-index.vue"),
},
{
path: "/dashboardA-hk",
name: "dashboardA-hk",
component:()=>import("@/viewsHK/dashboardA/dashboardA-index.vue"),
},
{
path: "/dashboardB-hk",
name: "dashboardB-hk",
component:()=>import("@/viewsHK/dashboardB/dashboardB-index.vue"),
},
{
path: "/dashboardC-hk",
name: "dashboardC-hk",
component:()=>import("@/viewsHK/dashboardC/dashboardC-index.vue"),
},
{
path: "/dashboardD-hk",
name: "dashboardD-hk",
component:()=>import("@/viewsHK/dashboardD/dashboardD-index.vue"),
},
]
});
export default router;
import { createStore } from 'vuex'
import { useRoute, useRouter } from "vue-router";
import router from '@/router.js'
export default createStore({
state: {
lang:"en"
},
mutations: {
},
actions: {
},
getters: {
},
modules: {
}
})
\ No newline at end of file
<script setup>
import layout from "./layout.vue"
const state=reactive({
APConfig:{
// backgroundFillAll:true,
// backgroundName:"A1",
height:930,
userSelect:true,
chartCount:9
}
})
</script>
<template>
<adaptivePanel :config="state.APConfig"><layout></layout></adaptivePanel>
</template>
<style lang="less">
</style>
\ No newline at end of file
<script setup>
import echartBarHoriz from "./portlet/echart-barHoriz.vue"
import echartLine from "./portlet/echart-line.vue"
import echartBarHorizScroll from "./portlet/echart-barHorizScroll.vue"
import echartGaugeTriple from "./portlet/echart-gaugeTriple.vue"
import echartSunburst from "./portlet/echart-sunburst.vue"
import counterGrid from "./portlet/counter-grid.vue"
import echartMap from "./portlet/echart-map.vue"
import mainNav from "@/common/mainNav.vue"
import externalLinks from "@/common/externalLinks.vue"
const comps = {
echartBarHoriz,
echartLine,
echartBarHorizScroll,
echartGaugeTriple,
echartSunburst,
echartMap,
counterGrid,
}
const state = reactive({
systemTitleConfig: {
width: 1000
},
panelTitleConfig: {
width: 160,
},
dialogConfig: {
show: false,
width: '60%',
height: '60%',
title: "对话框标题",
titleWidth: 350,
},
// panelTitleConfig:{
// width:180,
// theme:true
// },
areas: [
{
name: "left", portlets: [
{ id: "l2", title: "收支情况", component: "echartBarHoriz", border: "aYinTechBorderA1", hideTitle: true },
{ id: "l3", title: "业务收益情况", component: "echartLine", border: "aYinTechBorderA1", hideTitle: true },
{ id: "l1", title: "销售任务", component: "echartBarHorizScroll", border: "aYinTechBorderA1", hideTitle: true },
]
},
{
name: "right", portlets: [
{ id: "r1", title: "销售情况", component: "counterGrid", border: "blank", hideTitle: true },
{ id: "r2", title: "任务完成情况", component: "echartGaugeTriple", border: "aYinTechBorderA1", hideTitle: true },
{ id: "r3", title: "业务利润占比", component: "echartSunburst", border: "aYinTechBorderA1" },
]
},
]
})
const { systemTitleConfig, panelTitleConfig, areas } = toRefs(state)
const getConfig = (item) => {
const { id } = item
if (id == 'r3') {
return {
directionAlt: true,
rotate: "z",
opacity: 0.7
}
} else if (id.includes("l")) {
return {
title: item.title,
titleWidth: 120,
decoration: false,
decorationAlt: true,
rotate: "y",
opacity: 0.7
}
} else {
return {
title: item.title,
titleWidth: 120,
decoration: false,
opacity: .7
}
}
}
onMounted(() => {
})
</script>
<template>
<div class="screen1080A">
<mainNav></mainNav>
<externalLinks></externalLinks>
<div :class="`area-box area-${area.name}`" v-for="area in areas" :key="area.id">
<div class="portlet-wrapper" v-for="item in area.portlets" :key="item.id">
<component v-if="item.border" :is='item.border' :config="getConfig(item)">
<panelTitleA1 v-if="!item.hideTitle" :config="panelTitleConfig">{{ item.title }}</panelTitleA1>
<component :is='comps[item.component]'></component>
</component>
<template v-else>
<component :is='item.component'></component>
<i>{{ item.component }}</i>
</template>
</div>
</div>
<systemTitleA2 :config="systemTitleConfig">TechUI数据可视化成型工具</systemTitleA2>
<echartMap></echartMap>
</div>
</template>
<style lang="less">
.screen1080A {
z-index: 1;
padding: 60px 30px 30px 30px;
height: 100%; //url(../common/images/bg.png)
.techButtonA2 {
z-index: 10;
.poa;
bottom: 20px;
left: 50%;
.fixc("x");
}
.i() {
.poa;
bottom: 0;
right: 10px;
font-size: 12px;
opacity: .1;
.fc(@wh);
z-index: 10;
}
display: grid;
grid-template-columns: repeat(24, 1fr);
grid-template-rows:repeat(24, 1fr);
grid-gap: 30px;
.area-box {
.bdr(5px);
pointer-events: visible;
position: relative;
z-index: 10;
.board-3d-wrap {
.poa;
.fullbox;
}
//<row-start> / <column-start> / <row-end> / <column-end>;
.blank,
.portlet-wrapper {
.por;
>i {
.i;
}
}
.border-content {
>i {
.i;
}
}
&.area-left {
grid-area: 1 / 1 / 25 / 7;
}
&.area-right {
grid-area: 1 / 19 / 25 / 25;
.portlet-wrapper {
&:nth-child(3) {
grid-area: 3 / 1 /5/ 2
}
}
}
&.area-left {
display: grid;
grid-template-columns: repeat(1, 1fr);
grid-template-rows: repeat(3, 1fr);
grid-gap: 20px;
}
&.area-right {
display: grid;
grid-template-columns: repeat(1, 1fr);
grid-template-rows: repeat(4, 1fr);
grid-gap: 20px;
}
}
.content-tabs {
.poa;
top: -40px;
left: 80px;
right: 80px;
text-align: center;
height: 40px;
&:before {
content: " ";
.bdb(var(--button-bd_hov));
left: 0;
right: 0;
bottom: 10px;
.poa;
z-index: 1;
}
.tabs-item {
display: inline-block;
padding: 0 10px;
.ff("cn1");
.fc(var(--font-normal));
height: 30px;
line-height: 30px;
cursor: pointer;
.ani;
z-index: 2;
.por;
&:before {
content: " ";
.bgc(var(--button-bd_hov));
.poa;
.fullbox;
opacity: 0;
}
&:hover {
&:before {
opacity: .3;
}
}
&.active {
.bdb(var(--font-strong));
.fc(var(--font-strong));
}
}
}
}</style>
\ No newline at end of file
<script setup>
const state=reactive({
arry:[
{title:"软件销售额",icon:"i carbon:ibm-z-cloud-mod-stack",unit:"万元",total:"1874"},
{title:"硬件销售额",icon:"i carbon:chip",unit:"万元",total:"3276"},
{title:"技术服务",icon:"i carbon:user-speaker",unit:"万元",total:"315"},
{title:"安全服务",icon:"i carbon:rule",unit:"万元",total:"769"},
],
})
const borderConfig=(index)=>{
let rotate
if(index==0){
rotate="x";
}else if(index==1){
rotate="all";
}else if(index==2){
rotate=null;
}else if(index==3){
rotate="y";
}
return {
dur: 3,
opacity: 0.7,
// decoration: false,
rotate
}
}
</script>
<template>
<div class="screenA-counterGrid">
<aYinTechBorderB3 :config="borderConfig(index)" v-for="(item,index) in state.arry" :key="index">
<div class="inner-content">
<div class="block-title">{{item.title}} <span v-if="item.unit">({{item.unit}})</span></div>
<div class="total">
<i :class="[item.icon,'icon']"></i>
<!-- <DigitalTransform class="numbers" :value="123210" :interval="$vuex.state.globalConfig.ani?3000:0"></DigitalTransform> -->
<DigitalTransform class="numbers" :value="item.total" :useGrouping="true" :interval="3000"></DigitalTransform>
<!-- <span class="unit">{{item.unit}}</span> -->
</div>
</div>
</aYinTechBorderB3>
<!-- <div class="block" > <div class="bdTechBottom"></div> </div> -->
</div>
</template>
<style lang="less">
.screenA-counterGrid{display: grid; grid-template-columns: repeat(2,1fr); height: 100%; grid-template-rows: repeat(2,1fr); grid-gap: 12px; position: relative;
.aYinTechBorderB3{ padding:0; position: relative;
//&:nth-child(1){ grid-area: 1 / 1 / 2 / 3; }
.inner-content{
.block-title{position: absolute;.ff("cn1"); left:0; right:0; text-align: center; top:10px;.fc(var(--font-normal)); font-size: 14px; }
.total{margin: 0; text-align: center; line-height: 30px; .poa; left:0; right:0; top:60%; .fixc("y");
i{display:inline-block;font-size:32px; vertical-align: text-top; margin-right: 10px;.fc(var(--font-normal));}
.numbers{display:inline-block; text-align: center; font-size: 32px; .ff("en0"); position: relative; vertical-align: text-top; .fc(var(--font-strong));
.badge{position: absolute; left:100%; top:-10px; font-size: 14px; width: 30px; height:30px; padding:0; line-height: 1; }
}
.unit{font-size: 14px; margin:0 0 0 10px;.fc(var(--font-strong));}
}
}
}
}
</style>
<script setup>
const state=reactive({
chartData:{
legend:['本地视频会议', '异地视频会议'],
xAxis:['十二月', '一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月'],
colors:[$c.bll4,$c.aql4,$c.ipl3,$c.cbl3,],
data:[
[235, 210, 187, 212, 278, 220, 320, 302, 301, 334, 390, 330],
[68, 121, 34, 56, 23, 120, 132, 101, 134, 90, 230, 210]
],
},
chartOption:{}
})
const processData=()=>{
let legend=state.chartData.legend,
colors=state.chartData.colors,
xAxis=state.chartData.xAxis,
data=state.chartData.data,
processedData=[]
legend.forEach((item,i)=>{
processedData.push({
name: legend[i],
type: 'bar',
barWidth:15,
label: {
show: false,
position: 'insideRight'
},
itemStyle:{
color: colors[i],
borderRadius: 5
},
data: data[i]
})
})
state.chartOption.series=processedData;
state.chartOption.xAxis.data=xAxis;
}
const processOption=()=>{
state.chartOption={
update:false,
// title:{ text:"barA", left:200, top:0, textStyle:{ color:$c.gyl3, fontSize:16, fontWeight:"normal" }, },
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'shadow'
}
},
legend: {
//show:false,
data: [],
top:"5",
right:60,
},
toolbox: {
feature: {
magicType: { type: ['line', 'bar'] }
},
},
grid: {
left: '5%',
right: '5%',
bottom: '5%',
top: "15%",
containLabel: true
},
yAxis: {
type: 'value',
axisLabel: { align: 'right' }
},
xAxis: {
type: 'category',
data: [],
axisLabel: { align: 'center' }
},
series: []
}
processData()
}
onMounted(() => {
processOption();
})
</script>
<template>
<echartsInit :chartOption="state.chartOption"></echartsInit>
</template>
<style lang="less">
</style>
<script setup>
const state=reactive({
chartData:{
legend:['收入', '支出'],
yAxis:['业务1', '业务2', '业务3', '业务4', '业务5', '业务6'],
colors:[$c.cbl4,$c.bll5,],
data:[
[320, 302, 341, 374, 390, 450],
[-120, -132, -101, -134, -190, -230],
],
},
chartOption:{}
})
const processData=()=>{
let {legend,colors,yAxis,data}=state.chartData,
processedData=[];
legend.forEach((item,i)=>{
processedData.push({
name: legend[i],
type: 'bar',
barWidth:10,
stack: 'Total',
label: {
color:"#fff",
show: true
},
emphasis: {
focus: 'series'
},
itemStyle:{
color: $c.fade(colors[i],.9),
borderRadius: 3
},
data: data[i]
})
})
state.chartOption.legend.data=legend;
state.chartOption.series=processedData;
state.chartOption.yAxis.data=yAxis;
}
const processOption=()=>{
state.chartOption={
update:false,
// title:{ text:"barA", left:200, top:0, textStyle:{ color:$c.gyl3, fontSize:16, fontWeight:"normal" }, },
tooltip: {
trigger: 'axis',
axisPointer: { type: 'shadow' }
},
legend: {
right: '10',
top: '10',
},
grid: {
left: '5%',
right: '10%',
bottom: '8%',
top: "15%",
containLabel: true
},
xAxis: {
type: 'value',
axisLabel: {
align: 'center',
interval:0,
}
},
yAxis: {
type: 'category',
axisTick: {
show: false
},
data: [],
axisLabel: {
formatter: '{value}',
align: 'right'
}
}
}
processData();
}
onMounted(() => {
processOption();
})
</script>
<template>
<echartsInit :chartOption="state.chartOption"></echartsInit>
</template>
<style lang="less">
</style>
<script setup>
const base64Img="image://data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADoAAAA6CAMAAADWZboaAAAAZlBMVEUAAABe3uVe3+Vf3uVf3+Zf3uVg3+Zg3+Zf3+Vi4OZh4OZg3+Z86/Bh3+Zi4Odj4Odi4OZ86/B76/B86/Bj4ed56+9x5+xn4umB7/N87PB36e+A7/N+7fF/7vJ/7vJ+7fGA7/OB7/PReX+lAAAAIXRSTlMABQkVDREmIhk3MR10LEFFPHh7cUprXE35h2XnqMLAp+mHAG9cAAAB5ElEQVRIx83WjU7CMBQFYIoiKMqU/XUboHv/l/Tce7t2XamDNSacETEmX86tlK2rx4py150o+MstMBLwWRfHKo6JCVxLnvmFGBjFQ58oF1//sUZhGy/ClSTWObgnL4O+bkeN4nY2okfNMbkRt9/vtxz8InoTsWplJSCzFxPmO8+GpSIByX3YQAuGDWtRKhKjCnxDXhF6Z4yxnZ20Wgko7BMRDmxtSGVaI4kdTIgb+zTYoJQlIMlDlmUFgrcDWWC201qSayqlTkiCddWWeV62VU0YlnpRi9VOKaSUsiyq/N0krwq2Ugt7lVpZl5BfHNiytjagMi+XYp0kCR45hMlivVQrE/uU5pXSrCB5bM6d1t2lOZItMqmliT3q5uVxqxzyW/ccfYLNKx7ZTeykMvNyac2yt2Fbc61MHLSC0rwoxbiNdlQ3GBm1NLHQsHUrtEXppR/ljNpW6DbSCoqlFiVoN6YdaFlgsSFVPs1BdT8OaB5QyQzVcaqWDows/zepxR8ObLglTrdtCRVuRNj4Rrxh+//0ke2f8KVL+Kon3GCSbmsJN9OUW3j6g0Ns+LgCij2u0h+Sghc8mlMPBMgdx5DFh59VmOVHrvmDnoNxCz3J7MFWsMuaLyR089xz/xhlfijvwutR8gv3zk6BLUUeCgAAAABJRU5ErkJggg=="
const state=reactive({
chartData:{
yAxis:['任务A', '任务B', '任务C', '任务较长名称D', '任务E', '任务F', '任务G', '任务H', '任务I'],
color:[$c.cyl4,$c.orl5,$c.rel5],
data:[69, 96, 35,26, 96, 32 ,52 ,22 ,72]
},
chartOption:{}
})
const fillArr=computed(()=>{
return (new Array(state.chartData.data.length)).fill(100);
})
const getSymbolData=(data)=>{
let arr = [];
for (var i = 0; i < data.length; i++) {
arr.push({
value: data[i],
symbolPosition: 'end'
})
}
return arr;
}
const processData=()=>{
let legend=state.chartData.legend,
colors=state.chartData.colors,
yAxis=state.chartData.yAxis,
data=state.chartData.data,
processedData=[];
state.chartOption.yAxis.data=state.chartData.yAxis;
state.chartOption.series[0].data=state.chartData.data;
state.chartOption.series[1].data=fillArr;
state.chartOption.series[2].data=getSymbolData(state.chartData.data);
dataScroll();
}
const processOption=()=>{
state.chartOption={
update:false,
title: {
show:false,
// text: '实时流速图2',
textStyle:{
color:$c.cbl5,
fontSize:16,
fontWeight:"normal"
},
},
grid: {
top: '15%',
left: '18%',
right: '12%',
bottom: '5%'
},
tooltip: {show: false},
xAxis: {
type: 'value',
min: 0,
max: 100,
axisLine: {show: false},
splitLine: {show: false},
axisLabel: {show: false},
axisTick: {show: false}
},
dataZoom: {
yAxisIndex: 0,
show: false,
type: "slider",
startValue: 0,
endValue: 5,
},
yAxis: {
//show: false,
type: 'category',
inverse: true,
splitLine: {show: false,},
axisLine: {show: false},
axisLabel: {
show: true,
interval: 0,
margin: 10,
fontSize: 12,
width:50,
lineHeight:14,
overflow:"breakAll",
fontWeight: 'normal',
},
axisTick: {show: false},
data:[]
},
series: [
{
type: 'bar',
barWidth: '40%',
animationDuration:2000,
itemStyle: {
borderWidth:0,
borderRadius:10,
color: {
type: 'linear', x: 0, y: 0, x2: 1, y2: 0,
colorStops: [{ offset: 0, color: $c.cyl8, }, { offset: 1, color: $c.cyl4, }]
}
},
label: { show: false, },
data: [],
z: 0
},
{
type: 'bar',
barWidth: '40%',
barGap: '-100%',
animation: false,
itemStyle: {
borderWidth: 0,
borderRadius:5,
color: 'rgba(0,202,255,0.2)'
},
label: {
show: true,
position: ['101%', '20%'],
fontSize: 14,
fontWeight: 'normal',
formatter: (params)=>{
return ' ' + (state.chartData.data[params.dataIndex] ) + '%';
}
},
data: [],
z: 0
},
{
type: 'pictorialBar',
animation: true,
// animationThreshold: 3000 ,
animationDuration: 3000 ,
// animationDurationUpdate:500,
symbol: base64Img,
symbolSize: [50, 50],
symbolOffset: [20, 0],
z: 12,
itemStyle: {
color: '#fff'
},
data: []
},
]
}
processData();
}
const { proxy } = getCtx();
const dataScroll=()=>{
proxy.$timer("dataScrollBarHorizA",()=>{
let {data}=state.chartData
let {dataZoom}=state.chartOption
if (dataZoom.endValue == data.length ) {
dataZoom.endValue = 5;
dataZoom.startValue = 0;
}else{
dataZoom.endValue ++;
dataZoom.startValue ++;
}
state.chartOption.update=true
dataScroll()
},5000)
}
onMounted(() => {
processOption();
})
onBeforeMount(() => {
proxy.$timer("dataScrollBarHorizA")
})
</script>
<template>
<echartsInit :chartOption="state.chartOption"></echartsInit>
</template>
<style lang="less">
</style>
<script setup>
const state=reactive({
chartData:{
title:"任务完成情况",
legend:['开发任务1','采购任务2','销售任务3'],
colors:[$c.aql4, $c.cyl4,$c.cbl3],
colorsD:[$c.aql8,$c.cyl8,$c.bll8],
data:[72,14,36],
radius:["60%","75%","60%"],
position:[
['17%', '55%'],
['50%', '55%'],
['83%', '55%'],
],
},
chartOption:{}
})
const processData=()=>{
const {legend,colors,colorsD,data,radius,position}=state.chartData;
let processedData=[],
type="bar",
yAxisIndex=0;
legend.forEach((item,i)=>{
processedData.push({
type: 'gauge',
startAngle: 90,
endAngle: -270,
center: position[i],
radius: radius[i],
pointer: { show: false },
title: { fontSize: 14 },
itemStyle: {
color: colors[i],
shadowColor: colors[i],
},
progress: {
show: true,
overlap: false,
roundCap: true,
clip: false,
itemStyle: {}
},
detail: {
width: 50,
height: 14,
borderColor: 'inherit',
borderRadius: 20,
borderWidth: 0,
formatter: function (value) {
return '{value|' + value.toFixed(0) + '}{unit|%}';
},
rich: {
value: { fontSize: 24, color:colors[i], fontWeight: 'bolder'},// color: '#999',
unit: { fontSize: 12, color:$c.darken(colors[i],1),}
}
},
axisLine: {
lineStyle: {color: [[1, $c.darken(colors[i],4)]], width:10 }
},
splitLine: { show: false, distance: 0, length: 10 },
axisTick: { show: false },
axisLabel: { show: false, distance: 50 },
data:[
{
value: data[i],
name: legend[i],
title: { color:$c.lighten(colors[i],1), offsetCenter: ['0%', '30%'] },
detail: { valueAnimation: true, offsetCenter: ['0', '-30%'] }
}
],
})
})
state.chartOption.series=processedData;
}
const processOption=()=>{
state.chartOption={
update:false,
series: []
}
processData()
}
onMounted(() => {
processOption();
})
</script>
<template>
<echartsInit :chartOption="state.chartOption"></echartsInit>
</template>
<style lang="less">
</style>
<script setup>
const state=reactive({
chartData:{
legend:['本地', '异地'],
xAxis:['M1', 'M2', 'M3', 'M4', 'M5', 'M6', 'M7', 'M8', 'M9', 'M10', 'M11', 'M12'],
colors:[$c.aql4,$c.bll5,$c.ipl3,$c.cbl3,],
data:[
[ 230, 210,220,179,123, 120, 132, 101,168, 181, 134, 126, 134, 190, ],
[ 301, 334, 390, 330,300,240,235, 210, 187, 212, 278, 220, 320, 302,],
],
},
chartOption:{}
})
const processData=()=>{
let legend=state.chartData.legend,
colors=state.chartData.colors,
xAxis=state.chartData.xAxis,
data=state.chartData.data,
processedData=[]
legend.forEach((item,i)=>{
processedData.push({
name: legend[i],
type: 'line',
barWidth:15,
label: {
show: false,
position: 'insideRight'
},
itemStyle:{
color: colors[i],
borderRadius: 5
},
smooth: true,
areaStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
offset: 0,
color: $c.fade(colors[i],.9)
}, {
offset: 0.8,
color: $c.fade(colors[i],.1)
}], false),
shadowcolor: $c.fade(colors[i],.3),
shadowBlur: 10
},
data: data[i]
})
})
state.chartOption.series=processedData;
state.chartOption.xAxis.data=xAxis;
state.chartOption.legend.data=legend;
}
const processOption=()=>{
state.chartOption={
update:false,
// title:{ text:"barA", left:200, top:0, textStyle:{ color:$c.gyl3, fontSize:16, fontWeight:"normal" }, },
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'shadow'
}
},
legend: {
show:true,
data: [],
top:"5",
right:10,
},
// toolbox: {
// feature: {
// magicType: { type: ['line', 'bar'] }
// },
// },
grid: {
left: '5%',
right: '5%',
bottom: '5%',
top: "15%",
containLabel: true
},
yAxis: {
type: 'value',
axisLabel: {align: 'right' }
},
xAxis: {
type: 'category',
boundaryGap: false,
data: [],
axisLabel: { interval:0, align: 'center' }
},
series: []
}
processData()
}
onMounted(() => {
processOption();
})
</script>
<template>
<echartsInit :chartOption="state.chartOption"></echartsInit>
</template>
<style lang="less">
</style>
This diff is collapsed.
<script setup>
const state=reactive({
chartData:{
legend:['直接材料费','内部结算成本','其他直接费用','人工成本','折旧及摊销费','间接费用分摊数'],
colors:[$c.bll5,$c.inl3,$c.aql3,$c.yel3,$c.orl3,$c.rel3],
data:[325,252,323,183,120,43]
},
counter:{title:"费用总量",num:1723},
chartOption:{}
})
const processData=()=>{
let {legend,colors,data}=state.chartData,
processedData=[]
legend.forEach((item,i)=>{
processedData.push({
value:data[i],
name:legend[i],
itemStyle:{
color:colors[i]
}
})
})
state.chartOption.series[0].data=processedData;
state.chartOption.legend.data=legend;
}
const processOption=()=>{
state.chartOption={
update:false,
title:{
show:false,
text:"",
x:'center',
top:'32%',
textStyle:{
fontSize:24,
fontWeight:"bold",
lineHeight:30
},
},
tooltip: {
trigger: 'item',
formatter: "{a} <br/>{b}: {c} ({d}%)"
},
legend: {
orient: 'vertical',//horizontal
show:true,
right: '20',
top:'22%',
data:[],
formatter:(name)=>{
let target;
for(let i=0;i<state.chartData.data.length;i++){
if(state.chartData.legend[i]==name){
target=state.chartData.data[i]
}
}
return "{a|"+name+"}"+" "+"{b|"+target+"}"
},
textStyle:{
rich:{
a:{
fontSize:14,
color:$c.bll5,
padding:10
},
b:{
fontSize:16,
color:$c.cyl5
}
}
}
},
series: [
{
name:'数据类别',
type:'pie',
radius: ['40%', '65%'],
center: ['30%', '50%'],
//roseType: 'radius',
avoidLabelOverlap: false,
label: {
show: false,
position: 'outside',
},
itemStyle: {
borderRadius: 10,
borderColor: $c.bll9,
borderWidth: 5
},
emphasis: {
label:{
show: false,
fontSize: '20',
color:$c.gyd5,
}
},
labelLine: {
show: false
},
data:[]
}
]
}
processData()
}
onMounted(() => {
processOption();
})
</script>
<template>
<div class="echart-wrap">
<div class="total-digital">
<span class="desc">{{state.counter.title}}</span>
<DigitalTransform class="counter" :value="state.counter.num" :interval="1000" :dislocation="false" ></DigitalTransform>
</div>
<echartsInit :chartOption="state.chartOption"></echartsInit>
</div>
</template>
<style lang="less">
.echart-wrap{height: 100%;
.total-digital{.fc(@cyl5); text-align: center; width: 100px; .poa; top:52%; left:20%; .fixc("y");
.desc{display:block; font-size: 18px; margin:0 0 10px 0;}
.counter{display:block; .ff("en0"); font-size: 24px; font-weight: bold;}
}
}
</style>
<script setup>
const { proxy } = getCtx();
const state=reactive({
fontColor:$c.wh,
subFontColor:$c.cbl3,
chartData:{
title:"业务利润占比",
colors:[$c.aql7, $c.cyl5],
data:[
{
name: '软件',
children: [
{
name: '产品',value:123,
children: [
{ name: 'GIS系统', value: 49 },
{ name: '可视化', value: 25},
{ name: '财务系统', value: 11 }
]
},
{
name: '定制',value:90,
children: [
{ name: '业务系统', value: 35 },
{ name: '门户', value:15 }
]
}
]
},
{
name: '硬件', children: [
{
name: '服务器',value:230, children: [
{ name: '入门级', value: 43 },
{ name: '企业级', value: 121 }
]
},
{
name: '网管设备',value:55, children: [
{ name: '安全网关', value: 23 },
{ name: '路由器', value: 12 }
]
}
]
}
],
dataMax:300
},
chartOption:{},
dataOri:[]
})
const {dataOri,fontColor,subFontColor}=toRefs(state)
const mapLinkAction=(data,time)=>{
const {chartData}=state
data.forEach((item,i)=>{
if(time==1&&item.value){
let rmdval=i*proxy.randomNumber(time*10,100)
item.value=rmdval
chartData.dataMax+=rmdval
}else if(item.value){
delete item.value
}
if(item.children&&item.children.length>0){
const num=time-1
mapLinkAction(item.children,num)
}
})
}
const processData=()=>{
const {colors,data}=state.chartData;
let processedData=[],
type="bar",
yAxisIndex=0;
processedData.push({
type: 'sunburst',
data: data,
radius: [20, '80%'],
center:['53%','50%'],
itemStyle: {
borderRadius: 7,
borderWidth: 2,
borderColor:$c.bll9,
},
label: {
show: true,
color:fontColor,
fontSize: 12,
rotate: 'tangential'//文字旋转
// formatter: function (param) {
// return param.name+'\n'+param.value
// }
},
emphasis: {
label:{
show: true,
fontSize: '16',
color:$c.wh,
formatter: function (param) {
return param.name+'\n'+param.value
}
}
},
levels: [{},]
})
state.chartOption.series=processedData;
}
const processOption=()=>{
const {dataMax,colors}=state.chartData
state.chartOption={
update:false,
title:{
text:"数据单位:万元 点击数据可下钻",subtext:"", right:20, bottom:0,
textStyle:{ color:subFontColor, fontSize:12, fontWeight:"normal" },
},
visualMap: {
type: 'continuous',
left:10,
bottom:40,
min: 0,
max: dataMax,
inRange: {
color: colors
},
textStyle:{
color:fontColor,
},
},
series: []
}
processData();
}
onMounted(() => {
processOption();
})
</script>
<template>
<echartsInit :chartOption="state.chartOption"></echartsInit>
</template>
<style lang="less">
</style>
<script setup>
const state=reactive({
chartData:{
legend:['埋深'],
colors:[$c.bll5,],
data:[235, 210, 187, 212, 278, 220, 320, 302, 301, 334],
},
chartOption:{ }
})
const props=defineProps({
barColor:{
type:String,
default:""
},
})
const processData=()=>{
const {barColor}=props
let {colors,xAxis,data}=state.chartData,
processedData=[],
color=barColor?barColor:colors[0]
processedData.push({
type: "line",
symbolSize: 0,
label: { show: false, },
itemStyle:{
color: $c.fade(color,.1),
borderRadius: 3,
},
areaStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
offset: 0,
color: $c.fade(color,.9)
}, {
offset: 0.8,
color: $c.fade(color,.5)
}], false),
// shadowcolor: $c.fade(color,.3),
// shadowBlur: 10
},
smooth: true,
data: data
})
state.chartOption.series=processedData;
state.chartOption.xAxis.data=xAxis;
}
const processOption=()=>{
state.chartOption={
update:false,
// title:{ text:"barA", left:200, top:0, textStyle:{ color:$c.gyl3, fontSize:16, fontWeight:"normal" }, },
tooltip: {
trigger: 'axis',
axisPointer: { // 坐标轴指示器,坐标轴触发有效
type: 'shadow' // 默认为直线,可选为:'line' | 'shadow'
}
},
grid: {
left: 0,
right: 0,
bottom: 0,
top: 0,
},
yAxis:{
type: 'value',
axisLine: {show:false},
splitLine: {show:false},
axisLabel: {show:false}
},
xAxis: {
type: 'category',
boundaryGap: false,
data: [],
axisLine: {show:false},
splitLine: {show:false},
axisLabel: {show:false,}
},
series: []
}
processData();
}
onMounted(() => {
processOption();
})
</script>
<template>
<echartsInit :chartOption="state.chartOption"></echartsInit>
</template>
<style lang="less">
</style>
<template>
<!--本组件后续会封装成标注组件,通过参数来配置不同的风格和外观-->
<div class="map-counter-wrap">
<div class="counter-item" v-for="(item,index) in state.counterList">
<div class="content">
<DigitalTransform class="num" :value="item.num" :useGrouping="false" :interval="2000"></DigitalTransform>
</div>
<div class="name">{{item.name}} <span class="unit">({{item.unit}})</span></div>
<echartLine :barColor="item.barColor"></echartLine>
</div>
</div>
</template>
<script setup>
import echartLine from "./echart-line.vue"
const state=reactive({
counterList:[
{name:"软件年盈利",num:394,unit:"万元",barColor:$c.rel3},
{name:"硬件年盈利",num:42558,unit:"万元",barColor:$c.yel3},
{name:"服务年盈利",num:50262,unit:"万元"},
{name:"安全年盈利",num:50262,unit:"万元"},
]
})
</script>
<style lang="less">
.counter-item-re(){.bgc(fade(@red9,90%));
.name{.fc(@rer4);
.unit{.fc(@rer4);}
}
.content{
.num,
.num .plus{.fc(@rer4);}
}
}
.counter-item-ye(){.bgc(fade(@yed9,90%));
.name{.fc(@yer5);
.unit{.fc(@yer5);}
}
.content{
.num,
.num .plus{.fc(@yer5);}
}
}
.map-counter-wrap{.poa; left:50%; .fixc("x"); top:80px; z-index: 10;
.counter-item{ width: 190px; display:inline-block; .bgc(fade(@bll9,80%)); height: 60px; margin:0 20px 0 0; padding:10px 0 0 10px; position: relative;.bdr(5px);
.name{.fc(var(--font-normal)); font-size: 12px; .ff("cn1"); z-index: 1; .poa; left:5px; top:5px;
.unit{font-size: 12px;}
}
.content{.fc(var(--font-normal));.poa; right:5px; top:5px;
.num{font-size: 18px; .por; .ff(impact);.fc(var(--font-normal));
.plus{.poa; left:101%; top:-5px; font-size: 12px; .fc(var(--font-normal)); font-weight: normal; .ff("arial");}
}
}
.echartsInit-wrap{.poa!important; left:0; right:0; bottom:0; height: 25px!important;min-height: 25px!important;}
&:nth-child(1){.counter-item-re;}
&:nth-child(2){.counter-item-ye;}
&:nth-child(3){}
&:last-child{margin:0;}
}
}
</style>
{
"icon":"path://m569.52,440.01c18.46,31.99-4.71,71.99-41.58,71.99H48.05c-36.94,0-60-40.05-41.58-71.99L246.42,23.99c18.47-32.01,64.72-31.95,83.15,0l239.94,416.03h0Zm-281.52-86.01c-25.4,0-46,20.6-46,46s20.6,46,46,46,46-20.6,46-46-20.6-46-46-46Zm-43.67-165.35l7.42,136c.35,6.36,5.61,11.35,11.98,11.35h48.55c6.37,0,11.64-4.98,11.98-11.35l7.42-136c.38-6.87-5.1-12.65-11.98-12.65h-63.38c-6.88,0-12.36,5.78-11.98,12.65h0Z"
}
\ No newline at end of file
<script setup>
import layout from "./layout.vue"
const state=reactive({
APConfig:{
height:930,
backgroundFillAll:true,
backgroundName:"A2",
chartCount:9
}
})
</script>
<template>
<adaptivePanel :config="state.APConfig"><layout></layout></adaptivePanel>
</template>
<style lang="less">
</style>
\ No newline at end of file
<script setup>
import echartBarHoriz from "./portlet/echart-barHoriz.vue"
import echartBar from "./portlet/echart-bar.vue"
import echartLine from "./portlet/echart-line.vue"
import echartBarLine from "./portlet/echart-barLine.vue"
import echartBarHorizScroll from "./portlet/echart-barHorizScroll.vue"
import echartGaugeTriple from "./portlet/echart-gaugeTriple.vue"
import echartsRadar from "./portlet/echarts-radar.vue"
import echartPie from "./portlet/echart-pie.vue"
import echartsPictorialBar from "./portlet/echarts-PictorialBar.vue"
import counterGrid from "./portlet/counter-grid.vue"
import mainNav from "@/common/mainNav.vue"
import externalLinks from "@/common/externalLinks.vue"
const router = useRouter();
const { proxy } = getCtx();
const comps={
echartBarHoriz,
echartLine,
echartBar,
echartBarHorizScroll,
echartGaugeTriple,
echartsRadar,
counterGrid,
echartPie,
echartsPictorialBar,
echartBarLine
}
const state=reactive({
systemTitleConfig:{
width:500
},
panelTitleConfig:{
width:160,
},
dialogConfig:{
show:false,
width:'60%',
height:'60%',
title:"对话框标题",
titleWidth:350,
},
// panelTitleConfig:{
// width:180,
// theme:true
// },
areas:[
{name:"left",portlets:[
{id:"l2",title:"收支情况",component:"echartsPictorialBar",border:"aYinTechBorderA1",hideTitle:true},
{id:"l3",title:"业务收益情况",component:"echartBar",border:"aYinTechBorderA1",hideTitle:true},
{id:"l1",title:"销售任务",component:"echartsRadar",border:"aYinTechBorderA1",hideTitle:true},
]},
{name:"center",portlets:[
{id:"c1",title:"销售情况",component:"counterGrid",border:"blank",hideTitle:true},
{id:"c2",title:"任务完成情况",component:"echartPie",border:"aYinTechBorderA1",hideTitle:true},
{id:"c3",title:"业务利润占比",component:"echartGaugeTriple",border:"aYinTechBorderA1",hideTitle:true},
{id:"c4",title:"业务利润占比",component:"echartBarLine",border:"aYinTechBorderB4"},
]},
{name:"right",portlets:[
{id:"r1",title:"销售情况",component:"echartLine",border:"aYinTechBorderA1",hideTitle:true},
{id:"r2",title:"任务完成情况",component:"echartBarHoriz",border:"aYinTechBorderA1",hideTitle:true},
{id:"r3",title:"业务利润占比",component:"echartBarHorizScroll",border:"aYinTechBorderA1",hideTitle:true},
]},
]
})
const {systemTitleConfig,panelTitleConfig,dialogConfig,areas}=toRefs(state)
const chartCounter=computed(()=>{
return this.$vuex.state.adaptiveConfig.chartCounter;
})
const getConfig=(item)=>{
const {id}=item
if(id=='c2'){
return {
title:item.title,
opacity: 0.5,
decoration:false,
}
}else if(id=='c3'){
return {
title:item.title,
opacity: 0.5,
rotate:"y",
decoration:false,
}
}else if(id.includes("l")){
return {
title:item.title,
titleWidth:120,
decoration:false,
decorationAlt: true,
rotate: "y",
opacity: 0.5
}
}else{
return {
title:item.title,
titleWidth:120,
decoration:false,
opacity:.5
}
}
}
onMounted(()=>{ })
</script>
<template>
<div class="screen1080B">
<mainNav></mainNav>
<externalLinks></externalLinks>
<div :class="`area-box area-${area.name}`" v-for="area in areas" :key="area.id">
<div class="portlet-wrapper" v-for="item in area.portlets" :key="item.id">
<component v-if="item.border" :is='item.border' :config="getConfig(item)">
<panelTitleA1 v-if="!item.hideTitle" :config="panelTitleConfig" >{{item.title}}</panelTitleA1>
<component :is='comps[item.component]' ></component>
</component>
<template v-else>
<component :is='item.component'></component>
<i>{{item.component}}</i>
</template>
</div>
</div>
<systemTitleA1 :config="systemTitleConfig">TechUI数据可视化成型工具</systemTitleA1>
</div>
</template>
<style lang="less">
.screen1080B{ z-index: 1;padding:60px 30px 30px 30px; height: 100%; //url(../common/images/bg.png)
.techButtonA2 {z-index: 10; .poa; bottom:20px; left:50%; .fixc("x");}
.i(){.poa; bottom:0; right:10px; font-size: 12px; opacity: .1; .fc(@wh); z-index: 10;}
display: grid; grid-template-columns: repeat(24,1fr); grid-template-rows:repeat(24,1fr); grid-gap: 30px;
.area-box{.bdr(5px); pointer-events: visible; position: relative; z-index: 10;
.board-3d-wrap{ .poa; .fullbox;
}
//<row-start> / <column-start> / <row-end> / <column-end>;
.blank,
.portlet-wrapper{.por;
>i{.i;}
}
.border-content{>i{.i;}}
&.area-left{ grid-area: 1 / 1 / 25 / 7; }
&.area-right{ grid-area: 1 / 19 / 25 / 25; }
&.area-center{grid-area: 1 / 7 / 25 / 19; }
&.area-left,
&.area-right,
&.area-center{ display: grid; grid-template-columns: repeat(1,1fr); grid-template-rows:repeat(24,1fr); grid-gap: 20px;
.portlet-wrapper{
&:nth-child(1){grid-area: 1 / 1 / 8 / 3;}
&:nth-child(2){grid-area: 8 / 1 / 15 / 3;}
&:nth-child(3){grid-area: 15 / 1 / 25 / 3;}
}
}
&.area-center{grid-template-columns: repeat(2,1fr);
.portlet-wrapper{
&:nth-child(1){grid-area: 1 / 1 / 8 / 3;}
&:nth-child(2){grid-area: 8 / 1 / 15 / 2;}
&:nth-child(3){grid-area: 8/ 2 / 15 / 3;}
&:nth-child(4){grid-area: 15 / 1 / 25 / 3;}
}
}
}
.content-tabs{.poa; top:-40px; left:80px; right:80px; text-align: center; height: 40px;
&:before{content:" "; .bdb(var(--button-bd_hov));left:0; right:0; bottom:10px;.poa; z-index: 1;}
.tabs-item{display:inline-block; padding:0 10px; .ff("cn1"); .fc(var(--font-normal)); height: 30px;line-height: 30px; cursor: pointer; .ani; z-index: 2; .por;
&:before{content:" "; .bgc(var(--button-bd_hov)); .poa; .fullbox; opacity: 0;}
&:hover{&:before{opacity: .3;}}
&.active{ .bdb(var(--font-strong)); .fc(var(--font-strong));}
}
}
}
</style>
\ No newline at end of file
<script setup>
const state=reactive({
arry:[
{title:"软件销售额",icon:"i carbon:ibm-z-cloud-mod-stack",unit:"万元",total:"1874"},
{title:"硬件销售额",icon:"i carbon:chip",unit:"万元",total:"3276"},
{title:"技术服务",icon:"i carbon:user-speaker",unit:"万元",total:"315"},
{title:"安全服务",icon:"i carbon:rule",unit:"万元",total:"769"},
{title:"总支出费用",icon:"i carbon:airline-digital-gate",unit:"万元",total:"23769"},
],
})
const decoFrameConfig={
directionAlt: true,
scale:.8
}
</script>
<template>
<div class="screenB-counterGrid">
<div class="content-wrap" v-for="(item,index) in state.arry" :key="index">
<decoFrameA2 :config="decoFrameConfig"><i :class="[item.icon,'icon']"></i></decoFrameA2>
<DigitalTransform class="numbers" :value="item.total" :useGrouping="true" :interval="3000"></DigitalTransform>
<div class="block-title">{{item.title}} <span class="unit" v-if="item.unit">({{item.unit}})</span></div>
</div>
</div>
</template>
<style lang="less">
.screenB-counterGrid{ margin-top:30px; display: grid; grid-template-columns: repeat(5,1fr); height: 100%; grid-template-rows: repeat(1,1fr); grid-gap: 12px; position: relative;
.content-wrap{.por; text-align: center;
.decoFrameA2{margin:0 auto;}
.block-title{.ff("cn1"); .fc(@cbl3); font-size: 20px; line-height: 1.5;
.unit{display:block; font-size: 12px;}
}
.numbers{display:inline-block; text-align: center; height:38px; line-height: 1; font-size: 38px; .ff("en0"); position: relative; vertical-align: text-top; .fc(@cbl3); }
}
}
</style>
<script setup>
const state=reactive({
chartData:{
legend:['本地视频会议', '异地视频会议'],
xAxis:['十二月', '一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月'],
colors:[$c.bll4,$c.aql4,$c.ipl3,$c.cbl3,],
data:[
[235, 210, 187, 212, 278, 220, 320, 302],
[68, 121, 34, 56, 23, 120, 132, 101, 134]
],
},
chartOption:{}
})
const processData=()=>{
let legend=state.chartData.legend,
colors=state.chartData.colors,
xAxis=state.chartData.xAxis,
data=state.chartData.data,
processedData=[]
legend.forEach((item,i)=>{
processedData.push({
name: legend[i],
type: 'bar',
// barWidth:10,
label: {
show: false,
position: 'insideRight'
},
itemStyle:{
color: colors[i],
borderRadius: 5
},
data: data[i]
})
})
state.chartOption.series=processedData;
state.chartOption.xAxis.data=xAxis;
}
const processOption=()=>{
state.chartOption={
update:false,
// title:{ text:"barA", left:200, top:0, textStyle:{ color:$c.gyl3, fontSize:16, fontWeight:"normal" }, },
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'shadow'
}
},
legend: {
//show:false,
data: [],
top:"5",
right:60,
},
// toolbox: { feature: { magicType: { type: ['line', 'bar'] } }, },
grid: {
left: '5%',
right: '5%',
bottom: '5%',
top: "20%",
containLabel: true
},
yAxis: {
type: 'value',
axisLabel: {align: 'right' }
},
xAxis: {
type: 'category',
data: [],
axisLabel: { align: 'center' }
},
series: []
}
processData()
}
onMounted(() => {
processOption();
})
</script>
<template>
<echartsInit :chartOption="state.chartOption"></echartsInit>
</template>
<style lang="less">
</style>
<script setup>
const state=reactive({
chartData:{
legend:['收入', '支出'],
yAxis:['业务1', '业务2', '业务3', '业务4', '业务5', '业务6'],
colors:[$c.cbl4,$c.bll5,],
data:[
[320, 302, 341, 374, 390, 450],
[-120, -132, -101, -134, -190, -230],
],
},
chartOption:{}
})
const processData=()=>{
let {legend,colors,yAxis,data}=state.chartData,
processedData=[];
legend.forEach((item,i)=>{
processedData.push({
name: legend[i],
type: 'bar',
barWidth:10,
stack: 'Total',
label: {
color:$c.wh,
show: true
},
emphasis: {
focus: 'series'
},
itemStyle:{
color: $c.fade(colors[i],.9),
borderRadius: 3
},
data: data[i]
})
})
state.chartOption.legend.data=legend;
state.chartOption.series=processedData;
state.chartOption.yAxis.data=yAxis;
}
const processOption=()=>{
state.chartOption={
update:false,
// title:{ text:"barA", left:200, top:0, textStyle:{ color:$c.gyl3, fontSize:16, fontWeight:"normal" }, },
tooltip: {
trigger: 'axis',
axisPointer: { type: 'shadow' }
},
legend: {
left: '15',
top: '5',
},
grid: {
left: '5%',
right: '10%',
bottom: '8%',
top: "15%",
containLabel: true
},
xAxis: {
type: 'value',
axisLabel: {
align: 'center',
interval:0,
}
},
yAxis: {
type: 'category',
axisTick: {
show: false
},
data: [],
axisLabel: {
formatter: '{value}',
align: 'right'
}
}
}
processData();
}
onMounted(() => {
processOption();
})
</script>
<template>
<echartsInit :chartOption="state.chartOption"></echartsInit>
</template>
<style lang="less">
</style>
<script setup>
const base64Img="image://data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADoAAAA6CAMAAADWZboaAAAAZlBMVEUAAABe3uVe3+Vf3uVf3+Zf3uVg3+Zg3+Zf3+Vi4OZh4OZg3+Z86/Bh3+Zi4Odj4Odi4OZ86/B76/B86/Bj4ed56+9x5+xn4umB7/N87PB36e+A7/N+7fF/7vJ/7vJ+7fGA7/OB7/PReX+lAAAAIXRSTlMABQkVDREmIhk3MR10LEFFPHh7cUprXE35h2XnqMLAp+mHAG9cAAAB5ElEQVRIx83WjU7CMBQFYIoiKMqU/XUboHv/l/Tce7t2XamDNSacETEmX86tlK2rx4py150o+MstMBLwWRfHKo6JCVxLnvmFGBjFQ58oF1//sUZhGy/ClSTWObgnL4O+bkeN4nY2okfNMbkRt9/vtxz8InoTsWplJSCzFxPmO8+GpSIByX3YQAuGDWtRKhKjCnxDXhF6Z4yxnZ20Wgko7BMRDmxtSGVaI4kdTIgb+zTYoJQlIMlDlmUFgrcDWWC201qSayqlTkiCddWWeV62VU0YlnpRi9VOKaSUsiyq/N0krwq2Ugt7lVpZl5BfHNiytjagMi+XYp0kCR45hMlivVQrE/uU5pXSrCB5bM6d1t2lOZItMqmliT3q5uVxqxzyW/ccfYLNKx7ZTeykMvNyac2yt2Fbc61MHLSC0rwoxbiNdlQ3GBm1NLHQsHUrtEXppR/ljNpW6DbSCoqlFiVoN6YdaFlgsSFVPs1BdT8OaB5QyQzVcaqWDows/zepxR8ObLglTrdtCRVuRNj4Rrxh+//0ke2f8KVL+Kon3GCSbmsJN9OUW3j6g0Ns+LgCij2u0h+Sghc8mlMPBMgdx5DFh59VmOVHrvmDnoNxCz3J7MFWsMuaLyR089xz/xhlfijvwutR8gv3zk6BLUUeCgAAAABJRU5ErkJggg=="
const state=reactive({
chartData:{
yAxis:['任务A', '任务B', '任务C', '任务较长名称D', '任务E', '任务F', '任务G', '任务H', '任务I'],
color:[$c.cyl4,$c.orl5,$c.rel5],
data:[69, 96, 35,26, 96, 32 ,52 ,22 ,72]
},
chartOption:{}
})
const fillArr=computed(()=>{
return (new Array(state.chartData.data.length)).fill(100);
})
const getSymbolData=(data)=>{
let arr = [];
for (var i = 0; i < data.length; i++) {
arr.push({
value: data[i],
symbolPosition: 'end'
})
}
return arr;
}
const processData=()=>{
let legend=state.chartData.legend,
colors=state.chartData.colors,
yAxis=state.chartData.yAxis,
data=state.chartData.data,
processedData=[];
state.chartOption.yAxis.data=state.chartData.yAxis;
state.chartOption.series[0].data=state.chartData.data;
state.chartOption.series[1].data=fillArr;
state.chartOption.series[2].data=getSymbolData(state.chartData.data);
dataScroll();
}
const processOption=()=>{
state.chartOption={
update:false,
title: {
show:false,
// text: '实时流速图2',
textStyle:{
color:$c.cbl5,
fontSize:16,
fontWeight:"normal"
},
},
grid: {
top: '10%',
left: '18%',
right: '12%',
bottom: '5%'
},
tooltip: {show: false},
xAxis: {
type: 'value',
min: 0,
max: 100,
axisLine: {show: false},
splitLine: {show: false},
axisLabel: {show: false},
axisTick: {show: false}
},
dataZoom: {
yAxisIndex: 0,
show: false,
type: "slider",
startValue: 0,
endValue: 5,
},
yAxis: {
//show: false,
type: 'category',
inverse: true,
splitLine: {show: false,},
axisLine: {show: false},
axisLabel: {
show: true,
interval: 0,
margin: 10,
fontSize: 12,
width:50,
lineHeight:14,
overflow:"breakAll",
fontWeight: 'normal',
},
axisTick: {show: false},
data:[]
},
series: [
{
type: 'bar',
barWidth: '40%',
animationDuration:2000,
itemStyle: {
borderWidth:0,
borderRadius:10,
color: {
type: 'linear', x: 0, y: 0, x2: 1, y2: 0,
colorStops: [{ offset: 0, color: $c.cyl8, }, { offset: 1, color: $c.cyl4, }]
}
},
label: { show: false, },
data: [],
z: 0
},
{
type: 'bar',
barWidth: '40%',
barGap: '-100%',
animation: false,
itemStyle: {
borderWidth: 0,
borderRadius:5,
color: 'rgba(0,202,255,0.2)'
},
label: {
show: true,
position: ['101%', '20%'],
fontSize: 14,
fontWeight: 'normal',
formatter: (params)=>{
return ' ' + (state.chartData.data[params.dataIndex] ) + '%';
}
},
data: [],
z: 0
},
{
type: 'pictorialBar',
animation: true,
// animationThreshold: 3000 ,
animationDuration: 3000 ,
// animationDurationUpdate:500,
symbol: base64Img,
symbolSize: [50, 50],
symbolOffset: [20, 0],
z: 12,
itemStyle: {
color: '#fff'
},
data: []
},
]
}
processData();
}
const { proxy } = getCtx();
const dataScroll=()=>{
proxy.$timer("dataScrollBarHorizB",()=>{
let {data}=state.chartData
let {dataZoom}=state.chartOption
if (dataZoom.endValue == data.length ) {
dataZoom.endValue = 5;
dataZoom.startValue = 0;
}else{
dataZoom.endValue ++;
dataZoom.startValue ++;
}
state.chartOption.update=true
dataScroll()
},5000)
}
onMounted(() => {
processOption();
})
onBeforeMount(() => {
proxy.$timer("dataScrollBarHorizB")
})
</script>
<template>
<echartsInit :chartOption="state.chartOption"></echartsInit>
</template>
<style lang="less">
</style>
<script setup>
const state=reactive({
chartData:{
legend:['合同成本','毛利润','已回款', '已开票','毛利率%','回款率%'],
xAxis:['数据1', '数据2', '数据3', '数据4', '数据5', '数据6', '数据7', '数据8', '数据9', '数据10', '数据11', '数据12','数据13', '数据14', '数据15', '数据16', '数据17', '数据18', '数据19', '数据20', '数据21', '数据22', '数据23', '数据24'],
colors:[$c.aql2,$c.acl6,$c.bil4,$c.ipl4,$c.rel4,$c.yel3],
data:[
[235, 210, 187, 212, 278, 220, 320, 302, 301, 334, 390, 330,300,240,345,235, 210, 187, 212, 278, 220, 320, 302, 301, 334, 390, 330,300,240,345],
[22, 76, 13, 20,35, 30,20,9,13, 10, 50, 15,88,50, 85,22, 76, 13, 20,35, 60,20,9,13, 10, 80, 15,88,50, 85],
[193, 185, 122, 76, 70, 120, 135, 24,32,9,13, 110, 132, 53,88,193, 185, 122, 76, 32, 120, 135, 14,42,9,13, 110, 132, 12,88 ],
[35, 10,22,9,13, 10, 32, 15,0,93, 85, 22, 76, 13, 20,35, 10,0,9,13, 10, 32, 15,0,93, 85, 22, 76, 13, 20],
[5,20,9,13, 10, 22, 23, 13, 20,35,4, 15,37,0, 54,5,20,9,13, 10, 22, 23, 13, 20,35,4, 15,37,0, 54],
[35,0, 15,58,0,0,20,9,13, 10, 85, 22, 76, 13, 20,35,0, 15,58,0,0,20,9,13, 10, 85, 22, 76, 13, 20],
],
},
chartOption:{}
})
const processData=()=>{
let {legend,colors,xAxis,data}=state.chartData,
processedData=[],
yAxisIndex=0,
xName=[
"徽商银行关于2022年采购项目维保终端技术服务交换机合同",
"长城汽车诺博汽车系统徐采购项目维保终端技术服务交换机合同",
"中信银行济南分行4G采购项目维保终端技术服务交换机合同",
"中国科学院空天信息创采购项目维保终端技术服务交换机合同",
"中国信息创新研究院采购项目维保终端技术服务交换机合同",
"上海黄金交易所采购项目维保终端技术服务交换机合同",
"2022年苏州银行采购项目维保终端技术服务交换机合同",
"齐齐哈尔移动采购项目维保终端技术服务交换机合同",
"博时基金2022红帽采购项目维保终端技术服务交换机合同",
"航信远程监控项目采购项目维保终端技术服务交换机合同",
"全路通信信号设计院采购项目维保终端技术服务交换机合同",
"全路通信信号设计院服务器采购项目维保终端技术服务交换机合同",
"徽商银行关于2022年采购项目维保终端技术服务交换机合同",
"长城汽车诺博汽车系统徐采购项目维保终端技术服务交换机合同",
"中信银行济南分行4G采购项目维保终端技术服务交换机合同",
"中国科学院空天信息创采购项目维保终端技术服务交换机合同",
"中国信息创新研究院采购项目维保终端技术服务交换机合同",
"上海黄金交易所采购项目维保终端技术服务交换机合同",
"2022年苏州银行采购项目维保终端技术服务交换机合同",
"齐齐哈尔移动采购项目维保终端技术服务交换机合同",
"博时基金2022红帽采购项目维保终端技术服务交换机合同",
"航信远程监控项目采购项目维保终端技术服务交换机合同",
"全路通信信号设计院采购项目维保终端技术服务交换机合同",
"全路通信信号设计院服务器采购项目维保终端技术服务交换机合同"
];
xAxis.forEach((item,i)=>{
xAxis[i]=xName[i]//+"1"
})
legend.forEach((item,i)=>{
if(i>3){yAxisIndex=1}
processedData.push({
name: legend[i],
type: i>=legend.length-2?'line':'bar',
stack: i<2?'01':null,
barWidth:i==0?20:15,
label: {
show: false,
position: 'insideRight'
},
itemStyle:{
color: $c.fade(colors[i],.9),
borderRadius: 3,
},
z:10-i,
smooth: true,
areaStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: $c.fade(colors[i],.9) },
{ offset: 0.8, color: $c.fade(colors[i],.1) }
], false),
shadowcolor: $c.fade(colors[i],.3),
shadowBlur: 10
},
yAxisIndex:yAxisIndex,
data: data[i]
})
})
state.chartOption.legend.data=legend;
state.chartOption.series=processedData;
state.chartOption.xAxis.data=xAxis;
state.chartOption.xAxis.axisLabel.formatter=(str,index)=>{
// if (index % 2 != 0) { return '\n\n\n' + value; }
// else{ return value; }
let newstr= str, strLT=0,theNum=0;
for(let i=0;i<str.length;i++){
if(strLT<20){
if(str.charCodeAt(i)>255){
strLT++
}else{
strLT+=0.5
}
}else{
theNum=i;
break;
}
}
if(theNum>0){ newstr=newstr.substring(0,theNum)+"..."; }
return newstr;
}
}
const processOption=()=>{
state.chartOption={
update:false,
// title:{ text:"barA", left:200, top:0, textStyle:{ color:$c.gyl3, fontSize:16, fontWeight:"normal" }, },
tooltip: {
trigger: 'axis',
axisPointer: { // 坐标轴指示器,坐标轴触发有效
type: 'shadow' // 默认为直线,可选为:'line' | 'shadow'
}
},
legend: {
itemGap: 15,
left: 'center',
top: '50',
},
dataZoom:[
{
type: 'slider',
xAxisIndex: [0],
height: 30,
filterMode: 'filter',
bottom: 40,
start:0,
end:20,
show: true,
minSpan:5,
maxSpan:30,
moveHandleSize: 15 ,
showDetail:false
},
{
type: 'inside',// 内置于坐标系中
start: 0,
end: 20,
xAxisIndex: [0],
minSpan:5,
maxSpan:30
},
],
grid: {
left: '2%',
right: '2%',
bottom: '20%',
top: "25%",
containLabel: true
},
yAxis:[
{
type: 'value',
name: '单位:万元',
// min: 0,
// max: 300,
splitNumber: 3,
position: 'left',
axisLabel: {
formatter: '{value}',
align: 'right'
}
},
{
type: 'value',
name: '单位:%',
min: 0,
max: 100,
position: 'right',
offset: 0,
splitLine:{
show:false,
},
axisLabel: {
formatter: '{value}',
}
},
],
xAxis: {
type: 'category',
data: [],
axisLabel: {
align: 'center',
interval:0,
width:90,
lineHeight:14,
overflow:"breakAll",
margin:20,
},
},
series: []
}
processData()
}
onMounted(() => {
processOption();
})
</script>
<template>
<echartsInit :chartOption="state.chartOption"></echartsInit>
</template>
<style lang="less">
</style>
<script setup>
const state=reactive({
chartData:{
title:"任务完成情况",
legend:['开发任务1','采购任务2','销售任务3'],
colors:[$c.aql4, $c.cyl4,$c.cbl3],
colorsD:[$c.aql8,$c.cyl8,$c.bll8],
data:[72,14,36],
radius:["50%","65%","50%"],
position:[
['17%', '55%'],
['50%', '55%'],
['83%', '55%'],
],
},
chartOption:{}
})
const processData=()=>{
const {legend,colors,colorsD,data,radius,position}=state.chartData;
let processedData=[],
type="bar",
yAxisIndex=0;
legend.forEach((item,i)=>{
processedData.push({
type: 'gauge',
startAngle: 90,
endAngle: -270,
center: position[i],
radius: radius[i],
pointer: { show: false },
title: { fontSize: 14 },
itemStyle: {
color: colors[i],
shadowColor: colors[i],
},
progress: {
show: true,
overlap: false,
roundCap: true,
clip: false,
itemStyle: {}
},
detail: {
width: 50,
height: 14,
borderColor: 'inherit',
borderRadius: 20,
borderWidth: 0,
formatter: function (value) {
return '{value|' + value.toFixed(0) + '}{unit|%}';
},
rich: {
value: { fontSize: 24, color:colors[i], fontWeight: 'bolder'},// color: '#999',
unit: { fontSize: 12, color:$c.darken(colors[i],1),}
}
},
axisLine: {
lineStyle: {color: [[1, $c.darken(colors[i],4)]], width:10 }
},
splitLine: { show: false, distance: 0, length: 10 },
axisTick: { show: false },
axisLabel: { show: false, distance: 50 },
data:[
{
value: data[i],
name: legend[i],
title: { color:$c.lighten(colors[i],1), offsetCenter: ['0%', '30%'] },
detail: { valueAnimation: true, offsetCenter: ['0', '-30%'] }
}
],
})
})
state.chartOption.series=processedData;
}
const processOption=()=>{
state.chartOption={
update:false,
series: []
}
processData()
}
onMounted(() => {
processOption();
})
</script>
<template>
<echartsInit :chartOption="state.chartOption"></echartsInit>
</template>
<style lang="less">
</style>
<script setup>
const state=reactive({
chartData:{
legend:['本地', '异地'],
xAxis:['M1', 'M2', 'M3', 'M4', 'M5', 'M6', 'M7', 'M8', 'M9', 'M10', 'M11', 'M12'],
colors:[$c.aql4,$c.bll5,$c.ipl3,$c.cbl3,],
data:[
[ 230, 210,220,179,123, 120, 132, 101,168, 181, 134, 126, 134, 190, ],
[ 301, 334, 390, 330,300,240,235, 210, 187, 212, 278, 220, 320, 302,],
],
},
chartOption:{}
})
const processData=()=>{
let legend=state.chartData.legend,
colors=state.chartData.colors,
xAxis=state.chartData.xAxis,
data=state.chartData.data,
processedData=[]
legend.forEach((item,i)=>{
processedData.push({
name: legend[i],
type: 'line',
barWidth:15,
label: {
show: false,
position: 'insideRight'
},
itemStyle:{
color: colors[i],
borderRadius: 5
},
smooth: true,
areaStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
offset: 0,
color: $c.fade(colors[i],.9)
}, {
offset: 0.8,
color: $c.fade(colors[i],.1)
}], false),
shadowcolor: $c.fade(colors[i],.3),
shadowBlur: 10
},
data: data[i]
})
})
state.chartOption.series=processedData;
state.chartOption.xAxis.data=xAxis;
state.chartOption.legend.data=legend;
}
const processOption=()=>{
state.chartOption={
update:false,
// title:{ text:"barA", left:200, top:0, textStyle:{ color:$c.gyl3, fontSize:16, fontWeight:"normal" }, },
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'shadow'
}
},
legend: {
show:true,
data: [],
top:5,
left:15,
},
grid: {
left: '5%',
right: '5%',
bottom: '5%',
top: "20%",
containLabel: true
},
yAxis: {
type: 'value',
axisLabel: {align: 'right' }
},
xAxis: {
type: 'category',
boundaryGap: false,
data: [],
axisLabel: { interval:0, align: 'center' }
},
series: []
}
processData()
}
onMounted(() => {
processOption();
})
</script>
<template>
<echartsInit :chartOption="state.chartOption"></echartsInit>
</template>
<style lang="less">
</style>
This diff is collapsed.
<script setup>
const state=reactive({
chartData:{
legend:['软件','硬件','服务','安全','广告'],
colors:[$c.bll5,$c.inl3,$c.aql3,$c.yel3,$c.orl3,$c.rel3],
data:[325,252,323,183,120,43]
},
counter:{title:"费用总量",num:1723},
chartOption:{}
})
const processData=()=>{
let {legend,colors,data}=state.chartData,
processedData=[]
legend.forEach((item,i)=>{
processedData.push({
value:data[i],
name:legend[i],
itemStyle:{
color:colors[i]
}
})
})
state.chartOption.series[0].data=processedData;
state.chartOption.legend.data=legend;
}
const processOption=()=>{
state.chartOption={
update:false,
title:{
show:false,
text:"",
x:'center',
top:'32%',
textStyle:{
color:$c.bll5,
fontSize:24,
fontWeight:"bold",
lineHeight:30
},
},
tooltip: {
trigger: 'item',
formatter: "{a} <br/>{b}: {c} ({d}%)"
},
legend: {
orient: 'vertical',//horizontal
show:true,
right: '40',
top:'22%',
data:[],
formatter:(name)=>{
let target;
for(let i=0;i<state.chartData.data.length;i++){
if(state.chartData.legend[i]==name){
target=state.chartData.data[i]
}
}
return "{a|"+name+"}"+" "+"{b|"+target+"}"
},
textStyle:{
rich:{
a:{
fontSize:14,
color:$c.bll5,
padding:10
},
b:{
fontSize:16,
color:$c.cyl5
}
}
}
},
series: [
{
name:'数据类别',
type:'pie',
radius: ['55%', '80%'],
center: ['30%', '50%'],
//roseType: 'radius',
avoidLabelOverlap: false,
label: {
show: false,
position: 'outside',
},
itemStyle: {
borderRadius: 10,
borderColor: $c.bll9,
borderWidth: 5
},
emphasis: {
label:{
show: false,
fontSize: '20',
color:$c.gyd5,
}
},
labelLine: {
show: false
},
data:[]
}
]
}
processData()
}
onMounted(() => {
processOption();
})
</script>
<template>
<div class="echart-wrap-dashB">
<div class="total-digital">
<span class="desc">{{state.counter.title}}</span>
<DigitalTransform class="counter" :value="state.counter.num" :interval="1000" :dislocation="false" ></DigitalTransform>
</div>
<echartsInit :chartOption="state.chartOption"></echartsInit>
</div>
</template>
<style lang="less">
.echart-wrap-dashB{height: 100%;
.total-digital{.fc(@cyl5); text-align: center; width: 100px; .poa; top:52%; left:19%; .fixc("y");
.desc{display:block; font-size: 18px; margin:0 0 10px 0;}
.counter{display:block; .ff("en0"); font-size: 24px; font-weight: bold;}
}
}
</style>
<script setup>
const symbol = {
0:'path://M288,358.3c13.98-8.09,17.53-30.04,28.88-41.39s33.3-14.88,41.39-28.87c7.98-13.79,.17-34.54,4.37-50.29,4.06-15.25,20.46-29.25,20.46-45.75s-17.27-30.52-21.34-45.73c-4.21-15.75,3.61-36.5-4.36-50.29-8.09-13.98-30.03-17.52-41.38-28.87-11.35-11.35-14.89-33.3-28.87-41.39-13.79-7.98-34.54-.16-50.29-4.38-14.36-4.08-28.36-21.35-44.86-21.35s-30.5,17.27-45.7,21.34c-15.8,4.2-36.5-3.61-50.32,4.36-13.98,8.09-17.52,30.04-28.87,41.38-11.34,11.35-33.3,14.89-41.39,28.87-7.98,13.75-.16,34.55-4.37,50.25-4.08,15.3-21.35,29.3-21.35,45.8s17.27,30.52,21.34,45.73c4.21,15.75-3.61,36.5,4.36,50.29,8.1,13.98,30.04,17.48,41.38,28.88,11.35,11.35,14.89,33.3,28.88,41.4,13.79,7.98,34.53,.16,50.28,4.37,15.26,4.03,29.26,21.33,45.76,21.33s30.52-17.27,45.74-21.34c15.76-4.16,36.46,3.64,50.26-4.36ZM112,192c0-44.27,35.81-80,80-80s80,35.73,80,80-35.81,80-80,80-80-35.8-80-80ZM1.72,433.2c-3.25,8.19-1.78,17.48,3.87,24.25,5.66,6.75,14.53,9.9,23.12,8.15l45.19-9.04,21.43,42.27c4.13,8.17,12.27,13.17,21.37,13.17,.34,0,.66-.01,1.01-.03,9.5-.38,17.65-6.08,21.24-14.88l33.58-82.08c-53.71-4.64-102-28.12-138.2-63.95L1.72,433.2Zm347.88-82.1c-36.15,35.83-84.45,59.31-138.2,63.95l33.58,82.08c3.59,8.8,11.74,14.5,21.24,14.88,.38-.91-.12-.01,1.08-.01,9.09,0,17.23-4.97,21.35-13.14l21.43-42.28,45.19,9.04c8.59,1.75,17.47-1.4,23.12-8.15,5.66-6.77,7.12-16.06,3.88-24.25l-32.66-82.12Z',
};
const state=reactive({
chartData:{
legend:['预算成本'],
yAxis:["队伍A", "队伍B", "队伍C", "队伍D", "队伍E"],
colors:["#19e680","#00e8b8","#00e6df","#00c7f3","#009af3"],
colorsD:["#052e1a","#003328","#003331","#002a33","002033"],
data: [93, 85, 22, 76, 13],
},
chartOption:{ }
})
const processData=()=>{
let {legend,colors,colorsD,yAxis,data}=state.chartData,
processedData1={
tooltip: { show: false },
z: 4,
type: "pictorialBar",
symbolSize: ['20', '25'],
symbolRepeat: "fixed",
symbolMargin:12,
itemStyle:{
color: (item)=>{
return $c.fade(colorsD[item.dataIndex],.8)
},
},
data: []
},
processedData2={
z: 6,
type: "pictorialBar",
symbolSize: ['20', '25'],
animation: true,
symbolRepeat: "fixed",
symbolMargin:12,
symbolClip: true,
symbolPosition: "start",
symbolOffset: [0, 0],
itemStyle:{
color: (item)=>{
return $c.fade(colors[item.dataIndex],.8)
},
},
data: [],
label: { show: true, color: '#18fcff', fontSize: 14, position: "right", offset: [20, 0] },
};
data.forEach((item,i)=>{
processedData1.data.push(
{ value: 100, symbol: symbol[0], },
)
processedData2.data.push(
{ value: item, symbol: symbol[0], },
)
})
// state.chartOption.legend.data=legend;
state.chartOption.series[0]=processedData1;
state.chartOption.series[1]=processedData2;
state.chartOption.yAxis.data=yAxis;
}
const processOption=()=>{
state.chartOption={
update:false,
grid: {
left: "5%",
top: "20%",
bottom: "5%",
right: "20%",
containLabel: true
},
tooltip: {
trigger: "item",
},
xAxis: {
splitLine: { show: false },
axisLine: { show: false },
axisLabel: { show: false },
axisTick: { show: false }
},
yAxis:{
type: "category",
inverse: true,
data: [],
axisLine: { show: false },
axisTick: { show: false },
splitLine: { show: false, lineStyle: { type: "dashed" } },
axisLabel: { margin: 20, fontSize: 14, }
},
series: [ ]
}
processData()
}
onMounted(() => {
processOption();
})
</script>
<template>
<echartsInit :chartOption="state.chartOption"></echartsInit>
</template>
<style lang="less">
</style>
<script setup>
const state=reactive({
chartData:{
legend:['预算分配','实际开销'],
colors:[$c.bll5,$c.cyl5,],
data:[
[5000, 3400, 2800,4100, 4200, 2100],
[4300, 3000, 3700, 1500, 5000, 4900],
],
indicator: [
{ name: '销售', max: 5000,},
{ name: '管理', max: 5000, },
{ name: '技术', max: 5000, },
{ name: '客服', max: 5000, },
{ name: '研发', max: 5000, },
{ name: '市场', max: 5000, }
],
},
chartOption:{ }
})
const processData=()=>{
let {legend,colors,data,indicator}=state.chartData,
processedData=[]
legend.forEach((item,i)=>{
processedData.push({
name: legend[i],
type: "radar",
symbol: "circle",
color:colors[i],
symbolSize: 10,
areaStyle: {
color: $c.fade(colors[i],.4)
},
// itemStyle: {
// color: $c.fade(colors[i],.9),
// bordercolor: $c.fade(colors[i],.3),
// borderWidth: 10,
// },
lineStyle: {
color: $c.fade(colors[i],.9),
width: 2
},
data: [data[i]]
})
})
state.chartOption.legend.data=legend;
state.chartOption.series=processedData;
state.chartOption.radar.indicator=indicator;
}
const processOption=()=>{
state.chartOption={
update:false,
// title:{ text:"barA", left:200, top:0, textStyle:{ color:$c.gyl3, fontSize:16, fontWeight:"normal" }, },
title:{
text:"异常特征分布1",
show:false,
left:0,
top:0,
textStyle:{
color:$c.cbl5, fontSize:16, fontWeight:"normal"
},
},
tooltip: {
show: true,
trigger: "item"
},
legend: {
show:true,
right:15,
top:15,
width:50,
data: []
},
radar: {
center: ["50%", "53%"],
radius: "78%",
startAngle: 90,
splitNumber: 4,
shape: "circle",
splitArea: {
areaStyle: {
color: ["transparent"]
}
},
axisLabel: {
show: false,
fontSize: 12,
},
axisLine: {
show: true,
lineStyle: {
type: "dashed",
}
},
splitLine: {
show: true,
lineStyle: {
type: "dashed",
}
},
// shape: 'circle',
axisName: {
// formatter: '{a|{value}}{abg|}\n{hr|}\n{b|1234}',
// backgroundColor: '#eee',
// borderColor: '#aaa',
fontSize:14,
borderWidth: 1,
borderRadius: 0,
// rich: {
// a: { color: '#00b7ee', lineHeight: 25, padding: [0, 0, 0, 8], height: 25, backgroundColor: '#fff', borderRadius: 0 },
// hr: { borderColor: '#aaa', width: '100%', borderWidth: 0.1, align: 'left', height: 1 },
// b: { color: '#333', lineHeight: 25, padding: [0, 0, 0, 8], height: 25, backgroundColor: '#fff', width: '100%', align: 'left', borderRadius: 0 },
// per: { color: '#eee', backgroundColor: '#ffffff', borderWidth: 0.5, borderRadius: 0, borderColor: '#fff', }
// }
},
indicator: []
},
series: []
}
processData();
}
onMounted(() => {
processOption();
})
</script>
<template>
<echartsInit :chartOption="state.chartOption"></echartsInit>
</template>
<style lang="less">
</style>
This diff is collapsed.
This diff is collapsed.
<script setup>
const state=reactive({
chartData:{
legend:['埋深'],
colors:[$c.bll5,],
data:[235, 210, 187, 212, 278, 220, 320, 302, 301, 334],
},
chartOption:{ }
})
const props=defineProps({
barColor:{
type:String,
default:""
},
})
const processData=()=>{
const {barColor}=props
let {colors,xAxis,data}=state.chartData,
processedData=[],
color=barColor?barColor:colors[0]
processedData.push({
type: "line",
symbolSize: 0,
label: { show: false, },
itemStyle:{
color: $c.fade(color,.1),
borderRadius: 3,
},
areaStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
offset: 0,
color: $c.fade(color,.9)
}, {
offset: 0.8,
color: $c.fade(color,.5)
}], false),
// shadowcolor: $c.fade(color,.3),
// shadowBlur: 10
},
smooth: true,
data: data
})
state.chartOption.series=processedData;
state.chartOption.xAxis.data=xAxis;
}
const processOption=()=>{
state.chartOption={
update:false,
// title:{ text:"barA", left:200, top:0, textStyle:{ color:$c.gyl3, fontSize:16, fontWeight:"normal" }, },
tooltip: {
trigger: 'axis',
axisPointer: { // 坐标轴指示器,坐标轴触发有效
type: 'shadow' // 默认为直线,可选为:'line' | 'shadow'
}
},
grid: {
left: 0,
right: 0,
bottom: 0,
top: 0,
},
yAxis:{
type: 'value',
axisLine: {show:false},
splitLine: {show:false},
axisLabel: {show:false}
},
xAxis: {
type: 'category',
boundaryGap: false,
data: [],
axisLine: {show:false},
splitLine: {show:false},
axisLabel: {show:false,}
},
series: []
}
processData();
}
onMounted(() => {
processOption();
})
</script>
<template>
<echartsInit :chartOption="state.chartOption"></echartsInit>
</template>
<style lang="less">
</style>
<template>
<!--本组件后续会封装成标注组件,通过参数来配置不同的风格和外观-->
<div class="map-counter-wrap">
<div class="counter-item" v-for="(item,index) in state.counterList">
<div class="content">
<DigitalTransform class="num" :value="item.num" :useGrouping="false" :interval="2000"></DigitalTransform>
</div>
<div class="name">{{item.name}} <span class="unit">({{item.unit}})</span></div>
<echartLine :barColor="item.barColor"></echartLine>
</div>
</div>
</template>
<script setup>
import echartLine from "./echart-line.vue"
const state=reactive({
counterList:[
{name:"软件年盈利",num:394,unit:"万元",barColor:$c.rel3},
{name:"硬件年盈利",num:42558,unit:"万元",barColor:$c.yel3},
{name:"服务年盈利",num:50262,unit:"万元"},
{name:"安全年盈利",num:50262,unit:"万元"},
]
})
</script>
<style lang="less">
.counter-item-re(){.bgc(fade(@red9,90%));
.name{.fc(@rer4);
.unit{.fc(@rer4);}
}
.content{
.num,
.num .plus{.fc(@rer4);}
}
}
.counter-item-ye(){.bgc(fade(@yed9,90%));
.name{.fc(@yer5);
.unit{.fc(@yer5);}
}
.content{
.num,
.num .plus{.fc(@yer5);}
}
}
.map-counter-wrap{.poa; left:50%; .fixc("x"); top:80px; z-index: 10;
.counter-item{ width: 190px; display:inline-block; .bgc(fade(@bll9,80%)); height: 60px; margin:0 20px 0 0; padding:10px 0 0 10px; position: relative;.bdr(5px);
.name{.fc(var(--font-normal)); font-size: 12px; .ff("cn1"); z-index: 1; .poa; left:5px; top:5px;
.unit{font-size: 12px;}
}
.content{.fc(var(--font-normal));.poa; right:5px; top:5px;
.num{font-size: 18px; .por; .ff(impact);.fc(var(--font-normal));
.plus{.poa; left:101%; top:-5px; font-size: 12px; .fc(var(--font-normal)); font-weight: normal; .ff("arial");}
}
}
.echartsInit-wrap{.poa!important; left:0; right:0; bottom:0; height: 25px!important;min-height: 25px!important;}
&:nth-child(1){.counter-item-re;}
&:nth-child(2){.counter-item-ye;}
&:nth-child(3){}
&:last-child{margin:0;}
}
}
</style>
This diff is collapsed.
{
"icon":"path://m569.52,440.01c18.46,31.99-4.71,71.99-41.58,71.99H48.05c-36.94,0-60-40.05-41.58-71.99L246.42,23.99c18.47-32.01,64.72-31.95,83.15,0l239.94,416.03h0Zm-281.52-86.01c-25.4,0-46,20.6-46,46s20.6,46,46,46,46-20.6,46-46-20.6-46-46-46Zm-43.67-165.35l7.42,136c.35,6.36,5.61,11.35,11.98,11.35h48.55c6.37,0,11.64-4.98,11.98-11.35l7.42-136c.38-6.87-5.1-12.65-11.98-12.65h-63.38c-6.88,0-12.36,5.78-11.98,12.65h0Z"
}
\ No newline at end of file
This diff is collapsed.
<script setup>
import layout from "./layout.vue"
const state=reactive({
APConfig:{
height:930,
backgroundFillAll:true,
backgroundName:"A1",
chartCount:6
}
})
</script>
<template>
<adaptivePanel :config="state.APConfig"><layout></layout></adaptivePanel>
</template>
<style lang="less">
</style>
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment