Compare commits

..

5 Commits

Author SHA1 Message Date
时启龙 c4286682b0 docs: update README.md to specify pnpm version as 7+ 2024-12-17 16:30:58 +08:00
时启龙 eedde19492 docs: 更新 README.md,添加环境准备和快速开始指南,修改项目配置说明 2024-12-17 15:06:19 +08:00
时启龙 16b4496100 chore: 项目 -> 应用系统 2024-10-21 17:12:33 +08:00
时启龙 76e15dbf08 chore: 项目 -> 应用系统 2024-10-21 16:56:26 +08:00
时启龙 947199f6e4 chore: 增加忽略文件 2024-09-23 17:05:47 +08:00
257 changed files with 31250 additions and 32396 deletions

6
.env.development Normal file
View File

@ -0,0 +1,6 @@
/**
* Created by Zhang Haijun on 2018/8/13.
*/
VUE_APP_BASEURL = '/'
VUE_APP_MAPURL = 'http://58.210.9.131:5080'
VUE_APP_MAPTILE = '/SIPGIS/tile-services/TileService/SIPSD_sipmap/MapServer'

6
.env.production Normal file
View File

@ -0,0 +1,6 @@
/**
* Created by Zhang Haijun on 2018/8/13.
*/
VUE_APP_MAPURL = 'http://172.28.76.22'
VUE_APP_MAPTILE = '/SIPGIS/tile-services/TileService/ZNJT_GYYQ/MapServer'
VUE_APP_BASEURL = '/scr-web/'

View File

@ -5,9 +5,15 @@ module.exports = {
node: true node: true
}, },
extends: ['plugin:vue/essential', '@vue/standard'], extends: [
'plugin:vue/essential',
'@vue/standard',
'@vue/typescript'
],
parserOptions: {}, parserOptions: {
parser: '@typescript-eslint/parser'
},
rules: { rules: {
'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off', 'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',

1
.gitignore vendored
View File

@ -1,7 +1,6 @@
.DS_Store .DS_Store
node_modules node_modules
/scr-web /scr-web
*.zip
# local env files # local env files

8
Jenkinsfile vendored Normal file
View File

@ -0,0 +1,8 @@
@Library('jgpl') _
webPipeline([
onBuildInstallShell:{->
return """
pnpm install --no-frozen-lockfile
pnpm run build || echo 'Ignore build error !!!'
"""}
])

View File

@ -1,24 +1,45 @@
# cmp-screen # 博云 CMP Web 前端项目
## Project setup ## 环境准备
```
yarn install - Node.js 16+
- pnpm 7+
## 快速开始
1. 配置私有 NPM 源
```bash
# 设置 registry
npm config set registry http://58.210.154.140:13011/repository/bocloud-npm/
npm config set _auth Ym9jbG91ZDpjbXBAdjU4Nw==
# npm 相关配置
npm config set auto-install-peers=true
npm config set strict-peer-dependencies=false
npm config set shamefully-hoist=true
npm config set always-auth true
``` ```
### Compiles and hot-reloads for development 2. 安装依赖
```
yarn serve ```bash
pnpm install
``` ```
### Compiles and minifies for production 3. 本地开发
```
yarn build ```bash
pnpm run serve # 推荐:使用 vue-cli-service
``` ```
### Lints and fixes files 4. 项目构建
```
yarn lint ```bash
pnpm run build
``` ```
### Customize configuration ## 注意事项
See [Configuration Reference](https://cli.vuejs.org/config/).
- 不推荐使用 vite 进行开发,存在兼容性问题
- 建议使用 vue-cli-service serve 进行本地开发

30249
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,48 +1,71 @@
{ {
"name": "scr-web", "name": "cmp-screen",
"version": "5.6.0", "version": "5.6.0",
"private": true, "private": true,
"scripts": { "scripts": {
"serve": "vue-cli-service serve", "serve": "vue-cli-service serve",
"build": "vue-cli-service build", "build": "vue-cli-service build",
"lint": "vue-cli-service lint" "lint": "vue-cli-service lint"
}, },
"dependencies": { "dependencies": {
"@vue/composition-api": "1.7.1", "@antv/g6": "3.8.5",
"axios": "0.21.0", "@antv/l7": "^2.3.7",
"core-js": "3.6.5", "@antv/l7-district": "^2.3.1",
"echarts": "4.9.0", "@antv/l7-maps": "^2.3.7",
"echarts-liquidfill": "2.0.0", "@jiaminghi/data-view": "^2.10.0",
"element-ui": "2.14.1", "@turf/turf": "^6.3.0",
"js-cookie": "2.2.1", "@tweenjs/tween.js": "^18.6.4",
"lodash-es": "4.17.15", "@vue/composition-api": "^1.7.1",
"qs": "6.9.4", "axios": "^0.21.0",
"regenerator-runtime": "0.13.11", "cmp-echarts": "2.0.0-5.6-release",
"stats.js": "0.17.0", "core-js": "^3.6.5",
"url-loader": "4.1.1", "crypto-js": "^4.0.0",
"vue": "2.6.11", "echarts": "^4.9.0",
"vue-count-to": "1.0.13", "echarts-liquidfill": "^2.0.0",
"vue-router": "3.2.0", "element-ui": "^2.14.1",
"vue-seamless-scroll": "1.1.21", "heatmapjs": "^2.0.2",
"vuex": "3.4.0" "js-cookie": "^2.2.1",
}, "leaflet": "^1.7.1",
"devDependencies": { "lodash-es": "^4.17.15",
"@vue/cli-plugin-babel": "4.5.0", "moment": "^2.29.1",
"@vue/cli-plugin-eslint": "4.5.0", "nprogress": "^0.2.0",
"@vue/cli-plugin-router": "4.5.0", "ol": "^6.5.0",
"@vue/cli-plugin-vuex": "4.5.0", "ol-echarts": "^2.0.3",
"@vue/cli-service": "4.5.0", "qs": "^6.9.4",
"@vue/eslint-config-standard": "5.1.2", "regenerator-runtime": "^0.13.11",
"babel-eslint": "10.1.0", "stats.js": "^0.17.0",
"compress-webpack-plugin": "1.0.6", "three": "0.122.0",
"eslint": "6.7.2", "three-js-csg": "^72.0.0",
"eslint-plugin-import": "2.20.2", "three-orbitcontrols": "^2.110.3",
"eslint-plugin-node": "11.1.0", "url-loader": "^4.1.1",
"eslint-plugin-promise": "4.2.1", "vue": "^2.6.11",
"eslint-plugin-standard": "4.0.0", "vue-count-to": "^1.0.13",
"eslint-plugin-vue": "6.2.2", "vue-router": "^3.2.0",
"sass": "1.26.5", "vue-seamless-scroll": "^1.1.21",
"sass-loader": "8.0.2", "vuex": "^3.4.0"
"vue-template-compiler": "2.6.11" },
} "devDependencies": {
"@typescript-eslint/eslint-plugin": "^2.33.0",
"@typescript-eslint/parser": "^2.33.0",
"@vue/cli-plugin-babel": "~4.5.0",
"@vue/cli-plugin-eslint": "~4.5.0",
"@vue/cli-plugin-router": "~4.5.0",
"@vue/cli-plugin-typescript": "~4.5.0",
"@vue/cli-plugin-vuex": "~4.5.0",
"@vue/cli-service": "~4.5.0",
"@vue/eslint-config-standard": "^5.1.2",
"@vue/eslint-config-typescript": "^5.0.2",
"babel-eslint": "^10.1.0",
"compress-webpack-plugin": "^1.0.6",
"eslint": "^6.7.2",
"eslint-plugin-import": "^2.20.2",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-promise": "^4.2.1",
"eslint-plugin-standard": "^4.0.0",
"eslint-plugin-vue": "^6.2.2",
"sass": "^1.26.5",
"sass-loader": "^8.0.2",
"typescript": "^4.2.4",
"vue-template-compiler": "^2.6.11"
}
} }

13668
pnpm-lock.yaml Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,18 +1,23 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width,initial-scale=1.0" />
<link rel="icon" href="<%= BASE_URL %>static/img/logo.png" />
<title>高性能数值模拟实验平台</title>
</head>
<body> <head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>static/img/shortcut.png">
<title>
<%= htmlWebpackPlugin.options.title %>
</title>
<script type="text/javascript" src="./static/config.js"></script>
</head>
<body>
<noscript> <noscript>
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong> <strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript> </noscript>
<div id="app"></div> <div id="app"></div>
<!-- built files will be auto injected --> <!-- built files will be auto injected -->
</body> </body>
</html> </html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 106 KiB

BIN
public/static/img/jg.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 KiB

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 172 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 888 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 651 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

View File

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 117 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 116 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

BIN
public/static/img/ups.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

View File

@ -0,0 +1,3 @@
window.configs = {
showLogo: false
}

BIN
src/assets/img/animate.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.4 KiB

BIN
src/assets/img/header.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 926 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 566 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 93 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 121 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 240 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 110 KiB

BIN
src/assets/img/stat_bg.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 649 B

BIN
src/assets/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

View File

@ -0,0 +1,64 @@
<template>
<div class="scroll-wrapper" :style="style" @mouseenter="clearTimer" @mouseleave="enableTimer">
<slot :list="list"></slot>
</div>
</template>
<script>
import { computed, onMounted, onUnmounted, reactive, toRefs } from '@vue/composition-api'
export default {
props: {
data: {
type: Array
},
waitTime: {
type: Number,
default: 1500
},
singleHeight: {
type: Number,
default: 40
}
},
setup(props) {
const state = reactive({
animate: false
});
const list = computed(() => props.data);
const style = computed(() => {
return state.animate ? { transition: 'all 0.5s ease-in', transform: `translate(0, -${props.singleHeight}px)` } : {};
})
const scrollAnimate = () => {
state.animate = true;
setTimeout(() => {
state.animate = false;
list.value.push(list.value[0]);
list.value.shift();
}, 500)
}
let timer = null;
onMounted(() => {
enableTimer()
});
onUnmounted(() => {
clearTimer()
});
const enableTimer = () => {
if (timer) clearTimer();
timer = setInterval(scrollAnimate, props.waitTime)
}
const clearTimer = () => {
clearInterval(timer);
timer = null;
}
return {
...toRefs(state),
list,
style,
enableTimer,
clearTimer
}
}
}
</script>
<style lang="scss" scoped>
</style>

View File

@ -0,0 +1,55 @@
<template>
<div class="cell">
<img :src="icon" alt="" class="title-icon">
<div>
<div class="icon-container" v-for="(item, index) in data" :key="index">
<span class="icon" :style="{background: item.color}"></span>
<span class="text">{{item.text}}</span>
</div>
</div>
</div>
</template>
<script>
import { computed } from '@vue/composition-api'
export default {
props: {
icon: {
type: String,
default: '/scr-web/static/img/business_network/switch.png'
},
data: {
type: Array
}
},
setup(props) {
return {
}
}
}
</script>
<style lang="scss" scoped>
.cell {
display: flex;
margin-top: 20px;
justify-content: center;
align-items: center;
margin-bottom: 5px;
.title-icon{
width: 60px;
height: 80px;
margin-right: 10px;
}
span{
display: inline-block;
}
.icon-container{
margin-bottom: 5px;
}
.icon {
width: 14px;
height: 14px;
background: #19BE6B;
margin-right: 10px ;
}
}
</style>

View File

@ -2,7 +2,7 @@
<div class="full-screen-container" :style="style"> <div class="full-screen-container" :style="style">
<slot></slot> <slot></slot>
<div class="loading" v-if="loading"> <div class="loading" v-if="loading">
<dv-decoration-9 style="width: 300px; height: 300px">数据加载中</dv-decoration-9> <dv-decoration-9 style="width:300px;height:300px;" >数据加载中</dv-decoration-9>
</div> </div>
</div> </div>
</template> </template>
@ -28,36 +28,34 @@ export default {
}, },
setup(props, context) { setup(props, context) {
const state = reactive({ const state = reactive({
scale: { scale: null
wRatio: 1, });
hRatio: 1
}
})
const style = computed(() => { const style = computed(() => {
return { return {
width: `${props.width}px`, width: `${props.width}px`,
height: `${props.height}px`, height: `${props.height}px`,
transform: `scale(${state.scale.wRatio},${state.scale.hRatio})` transform: `scale(${state.scale})`
} }
}) });
function getScale() { function getScale() {
const { width, height } = props const { width, height } = props
const wRatio = window.innerWidth / width const wRatio = window.innerWidth / width
const hRatio = window.innerHeight / height const hRatio = window.innerHeight / height;
return { wRatio, hRatio } // return 1;
return wRatio < hRatio ? wRatio : hRatio
} }
function setScale() { function setScale() {
state.scale = getScale() state.scale = getScale();
context.emit('getScale', state.scale) context.emit('getScale', state.scale)
} }
const onResize = debounce(setScale, 10) const onResize = debounce(setScale, 10)
onMounted(() => { onMounted(() => {
setScale() setScale()
window.addEventListener('resize', onResize) window.addEventListener('resize', onResize)
}) });
onUnmounted(() => { onUnmounted(() => {
window.removeEventListener('resize', onResize) window.removeEventListener('resize', onResize)
}) });
return { return {
style style
} }
@ -65,7 +63,7 @@ export default {
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped >
.full-screen-container { .full-screen-container {
position: fixed; position: fixed;
top: 0px; top: 0px;
@ -73,18 +71,18 @@ export default {
overflow: hidden; overflow: hidden;
transform-origin: left top; transform-origin: left top;
z-index: 999; z-index: 999;
.loading { .loading{
width: 100%; width: 100%;
height: 100%; height: 100%;
position: fixed; position: fixed;
top: 0; top: 0;
left: 0; left: 0;
background: rgba(0, 0, 0, 0.8); background: rgba(0,0,0,0.8);
display: flex; display: flex;
flex-direction: column; flex-direction: column;
justify-content: center; justify-content: center;
align-items: center; align-items: center ;
color: rgba(255, 255, 255, 0.8); color: rgba(255,255,255,0.8);
font-size: 20px; font-size: 20px;
} }
} }

View File

@ -0,0 +1,59 @@
<template>
<div class="hello">
<h1>{{ msg }}</h1>
<p>
For a guide and recipes on how to configure / customize this project,<br>
check out the
<a href="https://cli.vuejs.org" target="_blank" rel="noopener">vue-cli documentation</a>.
</p>
<h3>Installed CLI Plugins</h3>
<ul>
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-typescript" target="_blank" rel="noopener">typescript</a></li>
</ul>
<h3>Essential Links</h3>
<ul>
<li><a href="https://vuejs.org" target="_blank" rel="noopener">Core Docs</a></li>
<li><a href="https://forum.vuejs.org" target="_blank" rel="noopener">Forum</a></li>
<li><a href="https://chat.vuejs.org" target="_blank" rel="noopener">Community Chat</a></li>
<li><a href="https://twitter.com/vuejs" target="_blank" rel="noopener">Twitter</a></li>
<li><a href="https://news.vuejs.org" target="_blank" rel="noopener">News</a></li>
</ul>
<h3>Ecosystem</h3>
<ul>
<li><a href="https://router.vuejs.org" target="_blank" rel="noopener">vue-router</a></li>
<li><a href="https://vuex.vuejs.org" target="_blank" rel="noopener">vuex</a></li>
<li><a href="https://github.com/vuejs/vue-devtools#vue-devtools" target="_blank" rel="noopener">vue-devtools</a></li>
<li><a href="https://vue-loader.vuejs.org" target="_blank" rel="noopener">vue-loader</a></li>
<li><a href="https://github.com/vuejs/awesome-vue" target="_blank" rel="noopener">awesome-vue</a></li>
</ul>
</div>
</template>
<script lang="ts">
import Vue from 'vue';
export default Vue.extend({
name: 'HelloWorld',
props: {
msg: String
}
});
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped lang="scss">
h3 {
margin: 40px 0 0;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
a {
color: #42b983;
}
</style>

View File

@ -0,0 +1,38 @@
<template>
<div class="no-data">
<i class="icon" :class="icon"></i>
<span class="text">{{text}}</span>
</div>
</template>
<script>
export default {
props: {
icon: {
type: String,
default: 'el-icon-s-order'
},
text: {
type: String,
default: '暂无数据'
}
}
}
</script>
<style lang="scss" scoped>
.no-data {
min-height: 200px;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
color: #fff;
.icon {
color: #1a84e6;
font-size: 50px;
margin-bottom: 10px;
}
.text {
color: #b3b5c3;
}
}
</style>

View File

@ -0,0 +1,106 @@
<template>
<el-row class="stat-container">
<!-- <dv-border-box-8 :reverse="true" style="height: 74px"> -->
<div class="stat-border" style="top: -2px"></div>
<div class="stat-border" style="top: -2px; right: 1px"></div>
<div class="stat-border" style="bottom: 0; right: 1px"></div>
<div class="stat-border" style="bottom: 0;"></div>
<el-col :span="24/configs.length" class="stat-part" v-for="item in configs" :key="item.title">
<div class="title">
<i class="icon" :class="item.icon"></i>
<span>{{item.title}}</span>
</div>
<div class="stat-count" v-for="(cell,index) in item.data" :key="index">
<template v-if="item.type === 'COUNT'">
<div>{{cell.title}}</div>
<div class="number" :class="cell.className" :style="cell.style">{{cell.value}} {{cell.unit}}</div>
</template>
<template v-if="item.type === 'PROGRESS'">
<div :style="item.titleStyle">{{cell.title}}</div>
<div class="progress-wrap">
<Progress :used="cell.used" :total="cell.total" :unit="cell.unit" :color="cell.color"></Progress>
</div>
</template>
</div>
</el-col>
<!-- </dv-border-box-8> -->
</el-row>
</template>
<script>
import Progress from 'components/progress'
export default {
components: { Progress },
props: {
configs: {
type: Array,
required: true
}
}
}
</script>
<style lang="scss" scoped>
.stat-container {
position: relative;
height: 74px;
width: 100%;
background: url('~assets/img/stat_bg.png');
border-bottom: 1px solid #0391d8;
border-top: 1px solid #0391d8;
margin: 10px 0;
.stat-border {
position: absolute;
width: 14px;
height: 2px;
background: #009ce0;
}
.stat-part {
display: flex;
align-items: center;
color: #fff;
height: 72px;
overflow: hidden;
.stat-count {
font-size: 17px;
flex: 1;
padding-left: 20px;
padding-right: 10px;
.number {
font-size: 25px;
font-weight: bold;
&.lgreen {
color: #42edf8;
}
&.green {
color: #39db3c;
}
&.purple {
color: #b34ef9;
}
&.yellow {
color: #ffc400;
}
}
}
.progress-wrap {
margin-top: 10px;
}
.title {
color: #fff;
height: 68px;
display: flex;
justify-content: center;
align-items: center;
font-size: 17px;
width: 140px;
background: #1b3c88;
.icon {
font-size: 28px;
margin-right: 5px;
}
span{
max-width: 90px;
}
}
}
}
</style>

View File

@ -0,0 +1,70 @@
<template>
<div class="outside-header">
<span>
<router-link to="/screen/list" v-if="logo">
<img class="logo" title="返回" :src="logo" alt="">
</router-link>
</span>
<span class="screen-title">
{{title}}
</span>
<span class="time"><span @click="operateScreen" title="全屏">{{currentTime}}</span></span>
</div>
</template>
<script>
import useHeader from 'components/ScreenWrapper/useHeader'
export default {
props: {
code: {
type: String,
required: true
}
},
setup(props, context) {
const { currentTime, operateScreen, logo, title } = useHeader(context.root.$store, props.code)
return {
currentTime,
logo,
title,
operateScreen
}
}
}
</script>
<style lang="scss" scoped>
.outside-header {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 93px;
background: url('~assets/img/header.gif');
background-size: 100% 100%;
display: flex;
& > span {
flex: 1;
}
.logo {
margin-left: 253px;
margin-top: 9px;
}
.screen-title {
text-align: center;
margin-left: 25px;
margin-top: 2px;
font-size: 48px;
color: #6Fffff;
}
.time {
font-size: 18px;
color: #fafbfd;
display: inline-block;
margin-top: 20px;
span {
cursor: pointer;
margin-left: 110px;
}
}
}
</style>

View File

@ -0,0 +1,103 @@
<template>
<full-screen-container class="container" :loading="loading" @getScale="scale => $emit('getScale', scale)">
<div class="header">
<span>
<router-link to="/screen/list" v-if="logo">
<img class="logo" title="返回" :src="logo" alt="">
</router-link>
</span>
<img :src="animateImg" alt="" class="left-animate">
<img :src="animateImg" alt="" class="right-animate">
<span class="screen-title">
{{title}}
</span>
<span class="time"><span @click="operateScreen" title="全屏">{{currentTime}}</span></span>
</div>
<div class="body">
<slot></slot>
</div>
</full-screen-container>
</template>
<script>
import useHeader from './useHeader'
import Header from './Header'
export default {
components: { Header },
props: {
code: {
type: String,
required: true
},
loading: {
type: Boolean,
default: false
}
},
setup(props, context) {
const { currentTime, operateScreen, logo, title } = useHeader(context.root.$store, props.code)
return {
currentTime,
logo,
animateImg: require('assets/img/animate.gif'),
title,
operateScreen
}
}
}
</script>
<style lang="scss" scoped>
.left-animate {
position: absolute;
left: 40px;
top: 100px;
}
.right-animate {
position: absolute;
right: 40px;
top: 100px;
}
.container {
width: 100vw;
height: 100vh;
min-height: 700px;
background: url('~assets/img/screen_bg.png') no-repeat;
background-size: 100% 100%;
overflow: hidden;
.header {
display: flex;
align-items: center;
height: 75px;
& > span {
flex: 1;
}
.logo {
margin-left: 210px;
}
.screen-title {
text-align: center;
margin-left: 25px;
margin-top: -2px;
font-size: 40px;
color: #6fffff;
}
.time {
font-size: 20px;
color: #fafbfd;
display: inline-block;
margin-top: -5px;
span {
cursor: pointer;
margin-left: 140px;
}
}
}
.body {
color: #fff;
padding: 40px 115px;
height: calc(100% - 100px);
box-sizing: border-box;
// display: flex;
}
}
</style>

View File

@ -1,25 +1,3 @@
import logo from '../images/logo.png'
import logo2 from '../images/logo2.png'
export default function() {
const title = '高性能数值模拟实验平台'
let isFull = false
function operateScreen() {
if (isFull) {
disableFullScreen()
} else {
enableFullScreen()
}
isFull = !isFull
}
return {
logo,
logo2,
title,
operateScreen
}
}
export function enableFullScreen() { export function enableFullScreen() {
const docElm = document.documentElement const docElm = document.documentElement
// W3C // W3C

View File

@ -0,0 +1,54 @@
import { reactive, toRefs, onUnmounted, ref, computed } from '@vue/composition-api'
import moment from 'moment'
import 'moment/locale/zh-cn'
import { enableFullScreen, disableFullScreen } from './tools'
import { getSystemConfigs } from 'services/system'
export default function (store, code) {
const title = computed(() => {
return store.getters.screenConfigs[code]
})
const state = reactive({
currentTime: ''
})
let timer = null
onUnmounted(() => {
clearInterval(timer)
timer = null
})
function setTimer() {
const getTime = () => {
const time = moment()
state.currentTime = `${time.format('YYYY年MM月DD日 dddd HH:mm:ss')}`;
}
getTime()
timer = setInterval(() => {
getTime()
}, 1000)
}
setTimer();
let isFull = false;
function operateScreen() {
if (isFull) {
disableFullScreen()
} else {
enableFullScreen()
}
isFull = !isFull;
}
// 获取logo
const logo = ref('');
async function getLogo () {
const data = await getSystemConfigs({ codes: 'loginLogo' });
if (data.success) {
logo.value = data.data.loginLogo;
}
}
if (window.configs?.showLogo) getLogo()
return {
...toRefs(state),
logo,
title,
operateScreen
}
}

View File

@ -1,8 +1,8 @@
<template> <template>
<div class="table-td" :title="value" :style="style"> <div class="table-td" :title="value" :style="style">
<slot :value="value"> <slot>
<el-tooltip class="item" effect="dark" :content="value.toString()" placement="top-start"> <el-tooltip class="item" effect="dark" :content="value.toString()" placement="top-start">
<span>{{ value }}</span> <span>{{value}}</span>
</el-tooltip> </el-tooltip>
</slot> </slot>
</div> </div>
@ -33,8 +33,6 @@ div.table-td {
overflow: hidden; overflow: hidden;
white-space: nowrap; white-space: nowrap;
text-overflow: ellipsis; text-overflow: ellipsis;
padding: 8px 5px; padding: 12px 5px;
display: flex;
justify-content: center;
} }
</style> </style>

View File

@ -2,19 +2,24 @@
<ul class="scroll-table"> <ul class="scroll-table">
<li class="table-header"> <li class="table-header">
<div v-for="(item, index) in columns" :key="item" :title="item" :style="getStyle(index)"> <div v-for="(item, index) in columns" :key="item" :title="item" :style="getStyle(index)">
<span>{{ item }}</span> <span>{{item}}</span></div>
</div>
</li> </li>
<div class="table-body"> <div class="table-body">
<li class="table-tr" v-for="(item, index) in data" :key="index"> <vueSeamlessScroll :data="data" :class-option="{singleHeight: 43, ...options}">
<slot :row="item"></slot> <li class="table-tr" v-for="(item, index) in data" :key="index">
</li> <slot :row="item"></slot>
<div v-if="!data.length"></div> </li>
</vueSeamlessScroll>
<NoData v-if="!data.length" ></NoData>
</div> </div>
</ul> </ul>
</template> </template>
<script> <script>
import { computed } from '@vue/composition-api'
import vueSeamlessScroll from 'vue-seamless-scroll'
import NoData from '../NoData'
export default { export default {
components: { vueSeamlessScroll, NoData },
props: { props: {
options: { options: {
type: Object, type: Object,
@ -27,7 +32,7 @@ export default {
}, },
columnWidth: { columnWidth: {
type: Array, type: Array,
default: function () { default: function() {
return [] return []
} }
}, },
@ -36,8 +41,8 @@ export default {
} }
}, },
setup(props) { setup(props) {
const getStyle = (index) => { const getStyle = index => {
const width = props.columnWidth[index] const width = props.columnWidth[index];
return width ? { width: width, flex: 'none' } : {} return width ? { width: width, flex: 'none' } : {}
} }
return { return {
@ -48,19 +53,13 @@ export default {
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.scroll-table { .scroll-table {
height: calc(100% - 20px); height: 100%;
color: #fff; color: #fff;
font-size: 14px; font-size: 12px;
padding: 0 10px; padding: 0;
margin: 10px 0 10 0;
padding-left: 0px;
text-align: center;
list-style: none; list-style: none;
.table-header { .table-header {
background: #152e6a; background: #152e6a;
background: url('../../images/table-header.png');
background-repeat: no-repeat;
background-size: 100% 100%;
color: #fff; color: #fff;
display: flex; display: flex;
div { div {
@ -73,18 +72,17 @@ export default {
} }
} }
.table-body { .table-body {
height: calc(100% - 50px); height: calc(100% - 37px);
overflow-y: hidden; overflow: hidden;
.table-tr { .table-tr {
display: flex; display: flex;
background: url('../../images/table-row.png'); &:nth-child(odd) {
background-repeat: no-repeat; background: #06153b;
background-size: 100% 32px; }
&:nth-child(even) {
background: rgba(60, 126, 241, 0.2);
}
} }
} }
.table-body::-webkit-scrollbar {
width: 0;
}
} }
</style> </style>

View File

@ -0,0 +1,55 @@
<template>
<div class="progress" >
<div class="content" :style="{ background: color, width: `${percent}%` }"></div>
<div class="text">{{percent.toFixed(2)}}%</div>
</div>
</template>
<script>
import { computed } from '@vue/composition-api'
export default {
props: {
percent: {
type: Number
}
},
setup(props) {
const color = computed(() => {
if (props.percent > 90) {
return '#F84540'
} else if (props.percent > 75) {
return '#FF9900'
} else if (props.percent > 50) {
return '#2D8CF0'
}
return '#19BE6B'
})
return {
color
}
}
}
</script>
<style lang="scss" scoped>
.progress {
width: 100%;
height: 12px;
position: relative;
background: #061330;
.content {
background: #19BE6B;
position: absolute;
top: 0;
left: 0;
height: 12px;
}
.text {
position: absolute;
right: 0;
top: -2px;
// margin-right: 2px;
font-size: 8px;
font-family: Microsoft YaHei;
color: #fff;
}
}
</style>

View File

@ -0,0 +1,172 @@
<template>
<div id="mountNode" style="height: 100%; width: 100%"></div>
</template>
<script>
import G6 from '@antv/g6';
import registerDefault from './registerDefault';
export default {
props: {
defaultEdgeType: {
type: String
},
defaultNodeType: {
type: String,
default: 'circle'
},
//
options: {
type: Object,
default: function() {
return {};
}
},
data: {
type: Object,
default: function() {
return {};
}
},
layout: {
type: Object
}
},
data() {
return {
graph: null,
currentLayout: ''
};
},
created() {
registerDefault(G6, this.defaultNodeType, this.defaultEdgeType);
},
mounted() {
this.initGraph();
window.addEventListener('resize', this.changeSize);
},
beforeUnmount() {
window.removeEventListener('resize', this.changeSize);
},
watch: {
data() {
if (this.graph) {
this.graph.changeData(this.data);
}
}
},
methods: {
initGraph() {
const target = document.getElementById('mountNode');
// const minimap = new G6.Minimap(this.minimapConfig);
// grid
const options = {
// plugins: [grid], // minimap
modes: {
default: [
'drag-canvas',
'zoom-canvas',
'drag-node',
'drag-combo'
// {
// type: 'tooltip', //
// formatText:
// this.tipFormat ||
// function(model) {
// //
// const text = [];
// text.push(`<div>${model.label}</div>`);
// return text.join('');
// },
// offset: 60
// }
] //
},
// fitCenter: true,
container: 'mountNode', // String | HTMLElement Step 1 id
width: target.offsetWidth, // Number
height: target.offsetHeight, // Number
defaultNode: {
type: 'image',
size: [60],
color: '#ffffff',
style: {
fill: '#9EC9FF',
lineWidth: 1
},
labelCfg: {
style: {
fill: '#ffffff',
fontSize: 12
},
position: 'bottom'
}
},
defaultEdge: {
type: 'circle-running',
style: {
stroke: '#7ECEF4',
lineWidth: 2
}
},
groupByTypes: false,
defaultCombo: {
type: 'rect',
padding: [40, 40, 40, 40],
style: {
fill: '#112A51',
stroke: '#112A51',
radius: 4
},
labelCfg: {
refY: 20,
refX: 20,
position: 'top',
style: {
fill: '#ffffff',
fontSize: 15
}
}
},
layout: this.layout
};
const graph = new G6.Graph(options);
this.graph = graph;
graph.read(this.data);
this.bindEvent();
},
save () {
const data = this.graph.save();
return data;
},
itemClick(evt, type) {
const { clientX, clientY, item } = evt;
const params = {
x: clientX, y: clientY, item: item.getModel()
}
this.$emit(type, params)
},
bindEvent() {
this.graph.on('node:click', evt => {
this.itemClick(evt, 'nodeClick')
});
this.graph.on('edge:click', evt => {
this.itemClick(evt, 'edgeClick')
});
this.graph.on('canvas:click', evt => {
this.$emit('canvasClick')
});
},
changeSize() {
setTimeout(() => {
const target = document.getElementById('mountNode');
const width = target.offsetWidth;
const height = target.offsetHeight;
this.graph.changeSize(width, height);
}, 1000);
}
}
};
</script>
<style lang="scss">
</style>

View File

@ -0,0 +1,129 @@
export default function registerDefault(
G6,
nodeType = 'circle',
lineType = 'quadratic'
) {
G6.registerNode(
'background-animate',
{
afterDraw(cfg, group) {
const r = cfg.size / 2;
const back1 = group.addShape('circle', {
zIndex: -3,
attrs: {
x: 0,
y: 0,
r,
fill: cfg.color,
opacity: 0.6
},
name: 'back1-shape'
});
const back2 = group.addShape('circle', {
zIndex: -2,
attrs: {
x: 0,
y: 0,
r,
fill: cfg.color,
opacity: 0.6
},
name: 'back2-shape'
});
const back3 = group.addShape('circle', {
zIndex: -1,
attrs: {
x: 0,
y: 0,
r,
fill: cfg.color,
opacity: 0.6
},
name: 'back3-shape'
});
group.sort(); // Sort according to the zIndex
back1.animate(
{
// Magnifying and disappearing
r: r + 10,
opacity: 0.1
},
{
duration: 3000,
easing: 'easeCubic',
delay: 0,
repeat: true // repeat
}
); // no delay
back2.animate(
{
// Magnifying and disappearing
r: r + 10,
opacity: 0.1
},
{
duration: 3000,
easing: 'easeCubic',
delay: 1000,
repeat: true // repeat
}
); // 1s delay
back3.animate(
{
// Magnifying and disappearing
r: r + 10,
opacity: 0.1
},
{
duration: 3000,
easing: 'easeCubic',
delay: 2000,
repeat: true // repeat
}
); // 3s delay
}
},
'image'
);
G6.registerEdge(
'circle-running',
{
afterDraw(cfg, group) {
// 获得当前边的第一个图形,这里是边本身的 path
const shape = group.get('children')[0];
// 边 path 的起点位置
const startPoint = shape.getPoint(0);
// 添加红色 circle 图形
const circle = group.addShape('circle', {
attrs: {
x: startPoint.x,
y: startPoint.y,
fill: '#29EEF7',
r: 3
},
name: 'circle-shape'
});
// 对红色圆点添加动画
circle.animate(
ratio => {
// 每一帧的操作,入参 ratio这一帧的比例值Number。返回值这一帧需要变化的参数集Object
// 根据比例值,获得在边 path 上对应比例的位置。
const tmpPoint = shape.getPoint(ratio);
// 返回需要变化的参数集,这里返回了位置 x 和 y
return {
x: tmpPoint.x,
y: tmpPoint.y
};
},
{
repeat: true, // 动画重复
duration: 3000 // 一次动画的时间长度
}
);
}
},
lineType
);
}

View File

@ -0,0 +1,76 @@
<template>
<bar-chart v-bind="$attrs"
:setting="configs"
></bar-chart>
</template>
<script>
import charts from 'cmp-echarts'
const { BarCharts } = charts
export default {
components: { BarChart: BarCharts },
props: {
setting: {
type: Object,
default() {
return {}
}
}
},
setup(props, context) {
const { rotate = 0 } = props.setting
const configs = {
series: {
label: {
show: true,
color: '#fff',
position: 'top'
}
},
legend: {
textStyle: {
color: '#fff'
},
pageIconColor: '#fff',
pageIconInactiveColor: '#2F4554'
},
xAxis: {
axisLabel: {
color: '#fff',
interval: 0,
rotate
},
axisLine: {
lineStyle: {
color: '#ffffff'
}
},
splitArea: {
show: false
}
},
yAxis: {
axisLabel: {
color: '#fff'
},
nameTextStyle: {
color: '#fff'
},
axisLine: {
lineStyle: {
color: '#ffffff'
}
},
splitLine: {
lineStyle: {
type: 'solid',
color: '#1B263D'
}
}
}
}
return {
configs
}
}
}
</script>

View File

@ -0,0 +1,60 @@
<template>
<bar-reverse-chart v-bind="$attrs"
:setting="configs"
></bar-reverse-chart>
</template>
<script>
import charts from 'cmp-echarts'
const { BarReverseCharts } = charts
const configs = {
series: {
label: {
show: true,
formatter: '{b}',
color: '#fff',
position: [10, -20]
}
},
legend: {
textStyle: {
color: '#fff'
}
},
xAxis: {
axisLabel: {
color: '#fff',
interval: 0
},
axisLine: {
lineStyle: {
color: '#ffffff'
}
},
splitArea: {
show: false
}
},
yAxis: {
axisLine: { show: false },
axisLabel: { show: false },
axisTick: { show: false },
splitLine: { show: false }
}
}
export default {
components: { BarReverseChart: BarReverseCharts },
props: {
setting: {
type: Object,
default() {
return {}
}
}
},
setup(props, context) {
return {
configs
}
}
}
</script>

View File

@ -0,0 +1,60 @@
<template>
<line-chart v-bind="$attrs"
:setting="setting"
></line-chart>
</template>
<script>
import charts from 'cmp-echarts'
import 'cmp-echarts/lib/cmp-echarts.css'
const { LineCharts } = charts
const setting = {
legend: {
textStyle: {
color: '#fff'
},
pageIconColor: '#fff',
pageIconInactiveColor: '#2F4554'
},
xAxis: {
axisLabel: {
color: '#fff'
},
axisLine: {
lineStyle: {
color: '#ffffff'
}
},
splitArea: {
show: false
}
},
yAxis: {
axisLabel: {
color: '#fff'
},
nameTextStyle: {
color: '#fff'
},
axisLine: {
lineStyle: {
color: '#ffffff'
}
},
splitLine: {
lineStyle: {
type: 'solid',
color: '#1B263D'
}
}
}
}
export default {
components: { LineChart: LineCharts },
setup(props, context) {
return {
setting
}
}
}
</script>

View File

@ -0,0 +1,72 @@
<template>
<pie-chart v-bind="$attrs"
:setting="setting"
></pie-chart>
</template>
<script>
import charts from 'cmp-echarts'
import { computed } from '@vue/composition-api'
const { PieCharts } = charts
export default {
props: {
configs: {
type: Object,
default() {
return {}
}
}
},
components: { PieChart: PieCharts },
setup(props, context) {
console.log(context)
const setting = computed(() => {
const { attrs: { data = [] } } = context;
const total = data.reduce((total, item) => {
return total + item.value / 1
}, 0)
return {
legend: {
textStyle: {
rich: {
name: {
align: 'left',
color: '#fff',
width: 50
},
count: {
align: 'right',
color: '#fff',
width: 50,
fontWeight: 600
}
}
}
},
series: {
label: {
show: true,
position: 'center',
formatter: function() {
return `{count|总数\r\n\r\n${total}}`
},
textStyle: {
color: '#fff'
},
rich: {
count: {
fontSize: 19,
color: '#fff'
}
}
},
itemStyle: {}
},
...props.configs
}
})
return {
setting
}
}
}
</script>

View File

@ -0,0 +1,191 @@
<template>
<div :style="{height:height,width:width}" class="chart-container">
<div class="chart" :class="{hide: isNoData}" :id="id" style="width: 100%;height: 100%"></div>
<NoData v-show="isNoData" class="chart-no-data"></NoData>
</div>
</template>
<script>
import mixins, { getLinerColor } from '../mixins'
import { yAxis, xAxis, grid } from '../defaultSetting'
import Axios from 'axios'
export default {
props: {
is3d: {
type: Boolean,
default: false
}
},
mixins: [mixins],
data () {
return {}
},
computed: {
isNoData() {
return !this.data.keys || !this.data.keys.length;
}
},
mounted () {
this.eveSet()
},
methods: {
//
eveSet () {
this.chart.on('click', (params) => {
const event = params.event.event
event.stopPropagation()
this.$emit('goToPage', params)
})
},
updateChart () {
const legends = []
const series = []
const { colorMap = {}, linerColor, axisLabel = {}, showSeriesLabel = true } = this.setting;
const color = (linerColor && linerColor.map(item => {
return getLinerColor(item[0], item[1])
}));
// [getLinerColor('#0089FF', '#A057A1')];
const { values = [], keys = [] } = this.data;
const { showLegend = false } = this.setting;
values.forEach((item, index) => {
legends.push(item.name)
const data = item.data.map(cell => {
return {
value: cell,
itemStyle: {
color: colorMap[item.name]
}
}
})
series.push({
name: item.name,
type: 'bar',
smooth: true,
stack: 'all',
barMaxWidth: 30,
label: {
show: showSeriesLabel,
position: 'top',
color: '#fff'
},
itemStyle: {
// normal: {
// areaStyle: { type: 'default' },
// color: new this.echarts.graphic.LinearGradient(
// 0, 0, 1, 1, [{
// offset: 0,
// color: startColor
// },
// {
// offset: 1,
// color: endColor
// }
// ]
// )
// }
},
data,
zlevel: 11
});
if (this.is3d) {
series.push({
type: 'bar',
barWidth: 8,
itemStyle: {
normal: {
color
}
},
barGap: 0,
data
}, {
name: 'b',
tooltip: {
show: false
},
type: 'pictorialBar',
itemStyle: {
borderWidth: 1,
borderColor: color[0],
color: color[0]
},
symbol: 'path://M 0,0 l 120,0 l -30,60 l -120,0 z',
symbolSize: ['30', '12'],
symbolOffset: ['0', '-8'],
symbolRotate: 5,
symbolPosition: 'end',
data,
z: 3
})
}
})
const options = {
color,
legend: {
show: showLegend,
top: 0,
textStyle: {
color: '#fff'
}
},
title: {
text: this.data.title
},
tooltip: {
trigger: 'axis',
...(this.setting.tooltip || {})
},
toolbox: this.setting.toolbox,
grid: {
...grid,
top: 30,
left: '1%',
right: '5%',
bottom: 1
},
xAxis: [{
...xAxis,
type: 'category',
name: this.unit,
splitLine: {
show: false
},
axisLabel: {
color: '#fff',
interval: 0,
...axisLabel
},
axisTick: {
show: false
},
data: this.data.keys.map(item => {
return item.replace(' ', '\n')
})
}],
yAxis: [{
...yAxis,
type: 'value',
splitLine: {
show: false
},
axisLabel: {
color: '#fff'
},
splitArea: {
show: false,
areaStyle: {
color: ['rgba(255,255,255,1)', 'rgba(248,251,255,1)']
}
}
}],
series: series
}
this.chart.setOption(options, true)
}
}
}
</script>
<style lang="scss" scoped>
@import '../index';
</style>

View File

@ -0,0 +1,2 @@
import BarCharts from './BarCharts.vue';
export default BarCharts;

View File

@ -0,0 +1,114 @@
<template>
<div :class="className" :id="id" :style="{height:height,width:width}"></div>
</template>
<script>
import mixins, { getLinerColor } from '../mixins'
import { yAxis, xAxis, grid } from '../defaultSetting'
export default {
mixins: [mixins],
data () {
return {}
},
mounted () {
this.eveSet()
},
methods: {
//
eveSet () {
this.chart.on('click', (params) => {
const event = params.event.event
event.stopPropagation()
this.$emit('goToPage', params)
})
},
updateChart () {
const legends = []
const series = []
const { barColor: [startColor = '#8699FF', endColor = '#4B66FF'] = [], yAxisLabel = {}, showXAxis = true } = this.setting;
this.data.values.forEach(item => {
legends.unshift(item.name)
series.push({
name: item.name,
type: 'bar',
smooth: true,
stack: 'all',
barMaxWidth: 11,
itemStyle: {
normal: {
// barBorderRadius: 5,
areaStyle: { type: 'default' },
color: getLinerColor(startColor, endColor)
}
},
data: item.data.reverse(),
zlevel: 11
})
})
const options = {
color: this.setting.color,
title: {
text: this.data.title
},
tooltip: {
trigger: 'axis'
},
toolbox: this.setting.toolbox,
grid: {
...grid,
top: 10,
left: '1%',
right: '5%'
},
xAxis: [{
show: showXAxis,
...xAxis,
type: 'value',
name: this.unit,
splitLine: {
show: false
},
axisTick: {
show: false
},
splitArea: {
show: false,
areaStyle: {
color: ['rgba(255,255,255,1)', 'rgba(248,251,255,1)']
}
},
axisLabel: {
color: '#fff'
}
}],
yAxis: [{
...yAxis,
type: 'category',
data: this.data.keys.map(item => {
return item.replace(' ', '\n')
}),
axisLine: {
show: false
},
splitLine: {
show: false
},
axisLabel: {
color: '#ffffff',
...yAxisLabel
},
splitArea: {
show: true,
areaStyle: {
color: ['rgba(0,0,0,0.0)', 'rgba(250,250,250,0.05)']
}
}
}],
series: series
}
this.chart.setOption(options, true)
}
}
}
</script>

View File

@ -0,0 +1,2 @@
import BarReverseCharts from './BarReverseCharts.vue';
export default BarReverseCharts;

View File

@ -0,0 +1,51 @@
export const legend = {
type: 'scroll',
itemWidth: 12,
itemHeight: 12,
icon: 'roundRect',
padding: [0, 20],
textStyle: {
color: '##999999'
}
};
export const grid = {
left: 1,
right: 1,
top: 30,
bottom: 1,
containLabel: true
};
export const yAxis = {
type: 'value',
nameGap: 5,
min: 0,
splitLine: {
lineStyle: {
color: ['#ebebeb'],
type: 'dashed'
}
},
axisLine: {
lineStyle: {
color: ['#d9d9d9']
}
},
axisTick: {
show: false
}
};
export const xAxis = {
axisLine: {
lineStyle: {
color: ['#d9d9d9']
}
},
axisTick: {
show: false
}
};
export const toolbox = {
feature: {
saveAsImage: {}
}
};

View File

@ -0,0 +1,66 @@
<template>
<div :class="className" :style="{height:height,width:width}" :id="id"></div>
</template>
<script>
import mixins from '../mixins';
export default {
mixins: [mixins],
data () {
return {};
},
methods: {
updateChart () {
const series = [];
series.push(
{
type: 'gauge',
center: ['50%', '55%'],
radius: '90%',
// min: this.data.min,
// max: this.data.max,
axisLine: { // 线
lineStyle: { // lineStyle线
width: 5
}
},
axisTick: { //
length: 15, // length线
lineStyle: { // lineStyle线
color: 'auto'
}
},
splitLine: { // 线
length: 10, // length线
lineStyle: { // lineStylelineStyle线
color: 'auto'
}
},
title: {
// 使TEXTSTYLE
fontWeight: 'bolder',
fontSize: 18,
color: '#fff'
},
axisLabel: {
fontSize: 8
},
detail: {
fontSize: 16
},
data: this.data
}
);
const options = {
tooltip: {
formatter: '{a} <br/>{c} {b}'
},
toolbox: this.setting.toolbox,
series: series
};
this.chart.setOption(options, true);
}
}
};
</script>

View File

@ -0,0 +1,5 @@
/**
* Created by Zhang Haijun on 2018/6/14.
*/
import GaugeCharts from './GaugeCharts.vue';
export default GaugeCharts;

View File

@ -0,0 +1,106 @@
<template>
<div :class="className" :id="id" :style="{height:height,width:width}"></div>
</template>
<script>
import mixins from '../mixins';
export default {
mixins: [mixins],
watch: {},
data () {
return {
chart: null
};
},
mounted () {
this.eveSet();
},
methods: {
//
hideOperate () {
const targetArr = document.getElementsByClassName('operate-node-menu');
for (const item of targetArr) {
item.style.display = 'none';
}
},
//
eveSet () {
this.chart.on('mouseup', (params) => {
if (params.dataType == 'edge') return;
const event = params.event.event;
event.stopPropagation();
if (event.button == 2) {
this.hideOperate();
this.$emit('mouseup', params);
}
});
const self = this;
document.addEventListener('click', function (event) {
event.stopPropagation();
self.hideOperate();
});
document.oncontextmenu = function () {
return false;
};
},
updateChart () {
const options = {
animationDuration: 100,
animationDurationUpdate: 300,
animationEasingUpdate: 'quinticInOut',
toolbox: this.setting.toolbox,
series: [
{
type: 'graph',
layout: 'force',
draggable: true,
symbolSize: 50,
roam: true, //
edgeSymbol: ['circle', 'none'],
edgeSymbolSize: [0, 10],
focusNodeAdjacency: true, //
lineStyle: {
normal: {
opacity: 1,
width: 1,
curveness: 0
}
},
label: {
normal: {
position: this.setting.labelPosition || 'bottom',
show: true,
textStyle: {
fontSize: 12
}
}
},
force: {
layoutAnimation: true, //
repulsion: [1000, 1200], //
edgeLength: [150, 200]//
},
edgeLabel: {
normal: {
show: true,
textStyle: {
fontSize: 12
},
formatter: '{c}',
backgroundColor: '#fff',
padding: 5,
color: '#4b59fd',
borderRadius: 3
}
},
data: this.data.nodes,
links: this.data.links
}
]
};
this.chart.setOption(options, true);
}
}
};
</script>

View File

@ -0,0 +1,2 @@
import GraphCharts from './GraphCharts.vue';
export default GraphCharts;

View File

@ -0,0 +1,18 @@
.chart-container {
position: relative;
width: 100%;
height: 100%;
.chart-no-data {
width: 100%;
color: #fff;
position: absolute;
top: 0;
}
.chart {
width: 100%;
height: 100%;
&.hide {
visibility: hidden;
}
}
}

View File

@ -0,0 +1,108 @@
<template>
<div :class="className" :id="id" :style="{height:height,width:width}"></div>
</template>
<script>
import mixins from '../mixins';
import { yAxis, xAxis } from '../defaultSetting';
export default {
mixins: [mixins],
data () {
return {};
},
methods: {
updateChart () {
const axisColor = '#ffffff'
const legends = [];
const series = [];
const { showLegend = true } = this.setting;
this.data.values.forEach(item => {
legends.push(item.name);
series.push({
name: item.name,
type: 'line',
symbol: 'none',
smooth: true,
areaStyle: {
opacity: 0.3
},
data: item.data
});
});
const options = {
color: this.setting.color,
title: {
text: this.data.title
},
tooltip: {
trigger: 'axis'
},
toolbox: this.setting.toolbox,
grid: {
left: 1,
right: 1,
top: 30,
bottom: 0,
containLabel: true
},
legend: {
show: showLegend,
type: 'scroll',
padding: [0, 20],
top: 0,
data: legends,
textStyle: {
color: '#fff'
}
},
xAxis: [{
...xAxis,
type: 'category',
data: this.data.keys.map(item => {
return item.replace(' ', '\n');
}),
axisLabel: {
color: axisColor || '#AAB3C0',
rotate: this.setting.axisLabelRotate
},
axisLine: {
lineStyle: {
color: '#ffffff'
}
},
splitArea: {
show: false,
areaStyle: {
color: ['rgba(255,255,255,1)', 'rgba(248,251,255,1)']
}
}
}],
yAxis: [{
...yAxis,
name: this.unit,
axisLabel: {
color: axisColor || '#AAB3C0'
},
nameTextStyle: {
color: axisColor || '#AAB3C0'
},
axisLine: {
lineStyle: {
color: '#ffffff'
}
},
splitLine: {
lineStyle: {
type: 'solid',
color: '#1B263D'
}
}
}],
series: series
};
this.chart.setOption(options, true);
}
}
};
</script>

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