余宏大屏

master
巴卫 1 year ago
commit d48877ce38

@ -0,0 +1,198 @@
module.exports = {
root: true,
parserOptions: {
parser: 'babel-eslint',
sourceType: 'module'
},
env: {
browser: true,
node: true,
es6: true,
},
extends: ['plugin:vue/recommended', 'eslint:recommended'],
// add your custom rules here
//it is base on https://github.com/vuejs/eslint-config-vue
rules: {
"vue/max-attributes-per-line": [2, {
"singleline": 10,
"multiline": {
"max": 1,
"allowFirstLine": false
}
}],
"vue/singleline-html-element-content-newline": "off",
"vue/multiline-html-element-content-newline":"off",
"vue/name-property-casing": ["error", "PascalCase"],
"vue/no-v-html": "off",
'accessor-pairs': 2,
'arrow-spacing': [2, {
'before': true,
'after': true
}],
'block-spacing': [2, 'always'],
'brace-style': [2, '1tbs', {
'allowSingleLine': true
}],
'camelcase': [0, {
'properties': 'always'
}],
'comma-dangle': [2, 'never'],
'comma-spacing': [2, {
'before': false,
'after': true
}],
'comma-style': [2, 'last'],
'constructor-super': 2,
'curly': [2, 'multi-line'],
'dot-location': [2, 'property'],
'eol-last': 2,
'eqeqeq': ["error", "always", {"null": "ignore"}],
'generator-star-spacing': [2, {
'before': true,
'after': true
}],
'handle-callback-err': [2, '^(err|error)$'],
'indent': [2, 2, {
'SwitchCase': 1
}],
'jsx-quotes': [2, 'prefer-single'],
'key-spacing': [2, {
'beforeColon': false,
'afterColon': true
}],
'keyword-spacing': [2, {
'before': true,
'after': true
}],
'new-cap': [2, {
'newIsCap': true,
'capIsNew': false
}],
'new-parens': 2,
'no-array-constructor': 2,
'no-caller': 2,
'no-console': 'off',
'no-class-assign': 2,
'no-cond-assign': 2,
'no-const-assign': 2,
'no-control-regex': 0,
'no-delete-var': 2,
'no-dupe-args': 2,
'no-dupe-class-members': 2,
'no-dupe-keys': 2,
'no-duplicate-case': 2,
'no-empty-character-class': 2,
'no-empty-pattern': 2,
'no-eval': 2,
'no-ex-assign': 2,
'no-extend-native': 2,
'no-extra-bind': 2,
'no-extra-boolean-cast': 2,
'no-extra-parens': [2, 'functions'],
'no-fallthrough': 2,
'no-floating-decimal': 2,
'no-func-assign': 2,
'no-implied-eval': 2,
'no-inner-declarations': [2, 'functions'],
'no-invalid-regexp': 2,
'no-irregular-whitespace': 2,
'no-iterator': 2,
'no-label-var': 2,
'no-labels': [2, {
'allowLoop': false,
'allowSwitch': false
}],
'no-lone-blocks': 2,
'no-mixed-spaces-and-tabs': 2,
'no-multi-spaces': 2,
'no-multi-str': 2,
'no-multiple-empty-lines': [2, {
'max': 1
}],
'no-native-reassign': 2,
'no-negated-in-lhs': 2,
'no-new-object': 2,
'no-new-require': 2,
'no-new-symbol': 2,
'no-new-wrappers': 2,
'no-obj-calls': 2,
'no-octal': 2,
'no-octal-escape': 2,
'no-path-concat': 2,
'no-proto': 2,
'no-redeclare': 2,
'no-regex-spaces': 2,
'no-return-assign': [2, 'except-parens'],
'no-self-assign': 2,
'no-self-compare': 2,
'no-sequences': 2,
'no-shadow-restricted-names': 2,
'no-spaced-func': 2,
'no-sparse-arrays': 2,
'no-this-before-super': 2,
'no-throw-literal': 2,
'no-trailing-spaces': 2,
'no-undef': 2,
'no-undef-init': 2,
'no-unexpected-multiline': 2,
'no-unmodified-loop-condition': 2,
'no-unneeded-ternary': [2, {
'defaultAssignment': false
}],
'no-unreachable': 2,
'no-unsafe-finally': 2,
'no-unused-vars': [2, {
'vars': 'all',
'args': 'none'
}],
'no-useless-call': 2,
'no-useless-computed-key': 2,
'no-useless-constructor': 2,
'no-useless-escape': 0,
'no-whitespace-before-property': 2,
'no-with': 2,
'one-var': [2, {
'initialized': 'never'
}],
'operator-linebreak': [2, 'after', {
'overrides': {
'?': 'before',
':': 'before'
}
}],
'padded-blocks': [2, 'never'],
'quotes': [2, 'single', {
'avoidEscape': true,
'allowTemplateLiterals': true
}],
'semi': [2, 'never'],
'semi-spacing': [2, {
'before': false,
'after': true
}],
'space-before-blocks': [2, 'always'],
'space-before-function-paren': [2, 'never'],
'space-in-parens': [2, 'never'],
'space-infix-ops': 2,
'space-unary-ops': [2, {
'words': true,
'nonwords': false
}],
'spaced-comment': [2, 'always', {
'markers': ['global', 'globals', 'eslint', 'eslint-disable', '*package', '!', ',']
}],
'template-curly-spacing': [2, 'never'],
'use-isnan': 2,
'valid-typeof': 2,
'wrap-iife': [2, 'any'],
'yield-star-spacing': [2, 'both'],
'yoda': [2, 'never'],
'prefer-const': 2,
'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0,
'object-curly-spacing': [2, 'always', {
objectsInObjects: false
}],
'array-bracket-spacing': [2, 'never']
}
}

@ -0,0 +1,21 @@
.DS_Store
node_modules
/dist
# local env files
.env.local
.env.*.local
# Log files
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?

@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

@ -0,0 +1,208 @@
**通知最新的低代码大屏系统GoView已开源详见[https://gitee.com/MTrun/go-view](https://gitee.com/MTrun/go-view)**
![输入图片说明](https://gitee.com/MTrun/go-view/raw/master/readme/logo-t-y.png)
## 一、项目描述
- 一个基于 Vue、Datav、Echart 框架的 " **数据大屏项目** ",通过 Vue 组件实现数据动态刷新渲染,内部图表可实现自由替换。部分图表使用 DataV 自带组件,可进行更改,详情请点击下方 DataV 文档。
- [**Vue3 版本请点击这里查看,使用 Hooks+TypeScript 实现,全新内容等你探索!**](https://gitee.com/MTrun/vue-big-screen-plugin)
- [**React 版本请点击这里查看,全新界面超级好看!!!**](https://gitee.com/MTrun/react-big-screen)
- 项目需要全屏展示(按 F11
- 项目部分区域使用了全局注册方式,增加了打包体积,在实际运用中请使用 **按需引入**。
- 拉取项目之后,建议按照自己的功能区域重命名文件,现以简单的位置进行区分。
- 项目环境Vue-cli-3.0、DataV-2.7.3、Echarts-4.6.0(如果5.x版本有问题请切换到4.x版本)、Webpack-4.0、Npm-6.13、Node-v12.16。
- 请拉取 master 分支的代码,其余分支是开发分支。
- 需要其它地图数据的,请查看我的其它项目(有一个地图合集)
友情链接:
1. [Vue 官方文档](https://cn.vuejs.org/v2/guide/instance.html)
2. [DataV 官方文档](http://datav.jiaminghi.com/guide/)
3. [echarts 实例](https://echarts.apache.org/examples/zh/index.html)[echarts API 文档](https://echarts.apache.org/zh/api.html#echarts)
项目展示
![项目展示](https://images.gitee.com/uploads/images/2020/1208/183608_b893a510_4964818.gif "20201208_221020.gif")
## 二、主要文件介绍
| 文件 | 作用/功能 |
| ------------------- | --------------------------------------------------------------------- |
| main.js | 主目录文件,引入 Echart/DataV 等文件 |
| utils | 工具函数与 mixins 函数等 |
| views/ index.vue | 项目主结构 |
| views/其余文件 | 界面各个区域组件(按照位置来命名) |
| assets | 静态资源目录,放置 logo 与背景图片 |
| assets / style.scss | 通用 CSS 文件,全局项目快捷样式调节 |
| assets / index.scss | Index 界面的 CSS 文件 |
| components/echart | 所有 echart 图表(按照位置来命名) |
| common/... | 全局封装的 ECharts 和 flexible 插件代码(适配屏幕尺寸,可定制化修改) |
## 三、使用介绍
### 启动项目
需要提前安装好 `nodejs``yarn`,下载项目后在项目主目录下运行 `yarn` 拉取依赖包。安装完依赖包之后然后使用 `vue-cli` 或者直接使用命令`npm run serve`,就可以启动项目,启动项目后需要手动全屏(按 F11。如果编译项目的时候提示没有 DataV 框架的依赖,输入 `npm install @jiaminghi/data-view` 或者 `yarn add @jiaminghi/data-view` 进行手动安装。
### 封装组件渲染图表
所有的 ECharts 图表都是基于 `common/echart/index.vue` 封装组件创建的,已经对数据和屏幕改动进行了监听,能够动态渲染图表数据和大小。在监听窗口小大的模块,使用了防抖函数来控制更新频率,节约浏览器性能。
项目配置了默认的 ECharts 图表样式,文件地址:`common/echart/theme.json`。
封装的渲染图表组件支持传入以下参数,可根据业务需求自行添加/删除。
参数名称 | 类型 | 作用/功能 |
| -------------------| --------- | ------------------------------|
| id | String | 唯一 id渲染图表的节点非必填使用了 $el|
| className | String | class样式名称非必填 |
| options | Object | ECharts 配置(必填) |
| height | String | 图表高度(建议填) |
| width | String | 图表宽度(建议填) |
### 动态渲染图表
动态渲染图表案例为 `components` 目录下各个图表组件index 文件负责数据获取和处理chart 文件负责监听和数据渲染。
chart 文件的主要逻辑为:
```html
<template>
<div>
<Echart :options="options" id="id" height="height" width="width" ></Echart>
</div>
</template>
<script>
// 引入封装组件
import Echart from '@/common/echart'
export default {
// 定义配置数据
data(){ return { options: {}}},
// 声明组件
components: { Echart},
// 接收数据
props: {
cdata: {
type: Object,
default: () => ({})
},
},
// 进行监听,也可以使用 computed 计算属性实现此功能
watch: {
cdata: {
handler (newData) {
this.options ={
// 这里编写 ECharts 配置
}
},
// 立即监听
immediate: true,
// 深度监听
deep: true
}
}
};
</script>
```
### 复用图表组件
复用图表组件案例为中间部分的 `任务通过率与任务达标率` 模块,两个图表类似,区别在于颜色和主要渲染数据。只需要传入对应的唯一 id 和样式,然后在复用的组件 `components/echart/center/centerChartRate` 里进行接收并在对应位置赋值即可。
如:在调用处 `views/center.vue` 里去定义好数据并传入组件
```js
//组件调用
<span>今日任务通过率</span>
<centerChart :id="rate[0].id" :tips="rate[0].tips" :colorObj="rate[0].colorData" />
<span>今日任务达标率</span>
<centerChart :id="rate[1].id" :tips="rate[1].tips" :colorObj="rate[1].colorData" />
...
import centerChart from "@/components/echart/center/centerChartRate";
data() {
return {
rate: [
{
id: "centerRate1",
tips: 60,
...
},
{
id: "centerRate2",
tips: 40,
colorData: {
...
}
}
]
}
}
```
### 更换边框
边框是使用了 DataV 自带的组件,只需要去 views 目录下去寻找对应的位置去查找并替换就可以,具体的种类请去 DavaV 官网查看
如:
```html
<dv-border-box-1></dv-border-box-1>
<dv-border-box-2></dv-border-box-2>
<dv-border-box-3></dv-border-box-3>
```
### 更换图表
直接进入 `components/echart` 下的文件修改成你要的 echarts 模样,可以去[echarts 官方社区](https://gallery.echartsjs.com/explore.html#sort=rank~timeframe=all~author=all)里面查看案例。
### Mixins 解决自适应适配功能
使用 mixins 注入解决了界面大小变动图表自适应适配的功能,函数在 `utils/resizeMixins.js` 中,应用在 `common/echart/index.vue` 的封装渲染组件,主要是对 `this.chart` 进行了功能注入。
### 屏幕适配
1.5 版本项目放弃了 flexible 插件方案,将 rem 改回px使用更流程通用的 `css3scale` 缩放方案,通过 `ref` 指向 `views/index`,屏幕改变时缩放内容。项目的基准尺寸是 `1920px*1080px`,所以支持同比例屏幕 100% 填充,如果非同比例则会自动计算比例居中填充,不足的部分则留白。实现代码在 `src/utils/userDraw` ,如果有其它的适配方案,欢迎交流。
### 请求数据
现在的项目未使用前后端数据请求,建议使用 axios 进行数据请求,在 main.js 位置进行全局配置。
- axios 的 main.js 配置参考范例(因人而异)
```js
import axios from 'axios';
//把方法放到vue的原型上这样就可以全局使用了
Vue.prototype.$http = axios.create({
//设置20秒超时时间
timeout: 20000,
baseURL: 'http://172.0.0.1:80080', //这里写后端地址
});
```
## 四、更新情况
1. 增加了 Echart 组件复用的功能,如:中间任务达标率的两个百分比图使用的是同一个组件。
2. 修复了头部右侧的图案条不对称的问题。
3. 使用 Mixins 注入图表响应式代码scale方案之后无需使用
4. vue-awesome 改成按需引入的方式。
5. 封装渲染函数,抽离了数据使逻辑更加清晰。
6. 新增地图组件,并添加自动轮播功能
7. 将适配方案从 rem 改成 scale
## 五、反馈
QQ群二维码
![输入图片说明](public/image.png)
## 六、相关大屏案例
(以下案例基于此项目二次开发):
1. https://gitee.com/memeda520/IofTV-Screen
## 五、七、其余
这个项目是个人的作品,难免会有问题和 BUG如果有问题请进行评论我也会尽力去更新自己也在前端学习的路上欢迎交流非常感谢

@ -0,0 +1,5 @@
module.exports = {
presets: [
'@vue/cli-plugin-babel/preset'
]
}

File diff suppressed because it is too large Load Diff

@ -0,0 +1,51 @@
{
"name": "big-screen-vue-datav",
"version": "1.5.1",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint"
},
"dependencies": {
"@jiaminghi/data-view": "^2.7.3",
"@types/echarts": "^4.4.3",
"axios": "^0.27.2",
"core-js": "^3.6.4",
"echarts": "^5.3.3",
"element-ui": "^2.15.9",
"vue": "^2.6.11",
"vue-awesome": "^4.0.2",
"vue-router": "^3.1.5",
"vuex": "^3.1.2"
},
"devDependencies": {
"@vue/cli-plugin-babel": "^5.0.8",
"@vue/cli-plugin-eslint": "^5.0.8",
"@vue/cli-service": "^5.0.8",
"babel-eslint": "^10.0.3",
"eslint": "^6.7.2",
"eslint-plugin-vue": "^6.1.2",
"sass": "^1.25.0",
"sass-loader": "^8.0.2",
"vue-template-compiler": "^2.6.11"
},
"eslintConfig": {
"root": true,
"env": {
"node": true
},
"extends": [
"plugin:vue/essential",
"eslint:recommended"
],
"parserOptions": {
"parser": "babel-eslint"
},
"rules": {}
},
"browserslist": [
"> 1%",
"last 2 versions"
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

@ -0,0 +1,17 @@
<!DOCTYPE html>
<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 %>favicon.ico">
<title><%= htmlWebpackPlugin.options.title %></title>
</head>
<body>
<noscript>
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>

@ -0,0 +1,14 @@
<template>
<div id="app">
<router-view />
</div>
</template>
<style lang="scss" scoped>
#app {
width: 100vw;
height: 100vh;
background-color: #020308;
overflow: hidden;
}
</style>

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 289 KiB

@ -0,0 +1,98 @@
//
$colors: (
"primary": #1A5CD7,
"info-1": #4394e4,
"info": #4b67af,
"white": #ffffff,
"light": #f9f9f9,
"grey-1": #999999,
"grey": #666666,
"dark-1": #5f5f5f,
"dark": #222222,
"black-1": #171823,
"black": #000000,
"icon": #5cd9e8
);
//
$base-font-size: 0.2rem;
$font-sizes: (
xxs: 0.1,
//8px
xs: 0.125,
//10px
sm: 0.2875,
//12px
md: 0.1625,
//13px
lg: 0.175,
//14px
xl: 0.2,
//16px
xxl: 0.225,
//18px
xxxl: 0.25 //20px,,,,
);
//
.w-100 {
width: 100%;
}
.h-100 {
height: 100%;
}
//flex
.d-flex {
display: flex;
}
.flex-column {
flex-direction: column;
}
.flex-wrap {
flex-wrap: wrap;
}
.flex-nowrap {
flex-wrap: nowrap;
}
$flex-jc: (
start: flex-start,
end: flex-end,
center: center,
between: space-between,
around: space-around,
evenly: space-evenly,
);
$flex-ai: (
start: flex-start,
end: flex-end,
center: center,
stretch: stretch,
);
.flex-1 {
flex: 1;
}
//.mt-1 => margin top
//spacing
$spacing-types: (
m: margin,
p: padding,
);
$spacing-directions: (
t: top,
r: right,
b: bottom,
l: left,
);
$spacing-base-size: 0.5rem;
$spacing-sizes: (
0: 0,
1: 0.5,
2: 1,
3: 1.5,
4: 2,
5: 2.5,
);

@ -0,0 +1,144 @@
#index {
color: #d3d6dd;
width: 1920px;
height: 1080px;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
transform-origin: left top;
overflow: hidden;
.bg {
width: 100%;
height: 100%;
padding: 16px 16px 0 16px;
background-image: url("../assets/pageBg.png");
background-size: cover;
background-position: center center;
}
.host-body {
.dv-dec-10,
.dv-dec-10-s {
width: 33.3%;
height: 5px;
}
.dv-dec-10-s {
transform: rotateY(180deg);
}
.dv-dec-8 {
width: 200px;
height: 50px;
}
.title {
position: relative;
width: 500px;
text-align: center;
background-size: cover;
background-repeat: no-repeat;
.title-text {
font-size: 24px;
position: absolute;
bottom: 0;
left: 50%;
transform: translate(-50%);
}
.dv-dec-6 {
position: absolute;
bottom: -30px;
left: 50%;
width: 250px;
height: 8px;
transform: translate(-50%);
}
}
//
.aside-width {
width: 40%;
}
.react-r-s,
.react-l-s {
background-color: #0f1325;
}
//
.react-right {
&.react-l-s {
text-align: right;
width: 500px;
}
font-size: 18px;
width: 300px;
line-height: 50px;
text-align: center;
transform: skewX(-45deg);
.react-after {
position: absolute;
right: -25px;
top: 0;
height: 50px;
width: 50px;
background-color: #0f1325;
transform: skewX(45deg);
}
.text {
display: inline-block;
transform: skewX(45deg);
}
}
.react-left {
&.react-l-s {
width: 500px;
text-align: left;
}
font-size: 18px;
width: 300px;
height: 50px;
line-height: 50px;
text-align: center;
transform: skewX(45deg);
background-color: #0f1325;
.react-left {
position: absolute;
left: -25px;
top: 0;
height: 50px;
width: 50px;
background-color: #0f1325;
transform: skewX(-45deg);
}
.text {
display: inline-block;
transform: skewX(-45deg);
}
}
.body-box {
margin-top: 16px;
display: flex;
flex-direction: column;
//
.content-box {
display: grid;
grid-template-columns: 2fr 3fr 5fr 3fr 2fr;
}
//
.bototm-box {
margin-top: 10px;
display: grid;
grid-template-columns: repeat(2, 50%);
}
}
}
}

@ -0,0 +1,185 @@
@import "./variables";
//
* {
margin: 0;
padding: 0;
list-style-type: none;
outline: none;
box-sizing: border-box;
}
html {
margin: 0;
padding: 0;
}
body {
font-family: Arial, Helvetica, sans-serif;
line-height: 1.2em;
background-color: #f1f1f1;
margin: 0;
padding: 0;
}
a {
color: #343440;
text-decoration: none;
}
.clearfix {
&::after {
content: "";
display: table;
height: 0;
line-height: 0;
visibility: hidden;
clear: both;
}
}
//
.float-r {
float: right;
}
//
.float-l {
float: left;
}
//
.fw-b {
font-weight: bold;
}
//
.title-item {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.bg-color-black {
background-color: rgba(19, 25, 47, 0.6);
}
.bg-color-blue {
background-color: #1a5cd7;
}
.colorBlack {
color: #272727 !important;
&:hover {
color: #272727 !important;
}
}
.colorGrass {
color: #33cea0;
&:hover {
color: #33cea0 !important;
}
}
.colorRed {
color: #ff5722;
&:hover {
color: #ff5722 !important;
}
}
.colorText {
color: #d3d6dd !important;
&:hover {
color: #d3d6dd !important;
}
}
.colorBlue {
color: #257dff !important;
&:hover {
color: #257dff !important;
}
}
//
@each $colorkey, $color in $colors {
.text-#{$colorkey} {
color: $color;
}
.bg-#{$colorkey} {
background-color: $color;
}
}
//
@each $var in (left, center, right) {
.text-#{$var} {
text-align: $var !important;
}
}
//flex
@each $key, $value in $flex-jc {
.jc-#{$key} {
justify-content: $value;
}
}
@each $key, $value in $flex-ai {
.ai-#{$key} {
align-items: $value;
}
}
//
@each $fontkey, $fontvalue in $font-sizes {
.fs-#{$fontkey} {
font-size: $fontvalue * $base-font-size;
}
}
//.mt-1 => margin top
//spacing
@each $typekey, $type in $spacing-types {
//.m-1
@each $sizekey, $size in $spacing-sizes {
.#{$typekey}-#{$sizekey} {
#{$type}: $size * $spacing-base-size;
}
}
//.mx-1
@each $sizekey, $size in $spacing-sizes {
.#{$typekey}x-#{$sizekey} {
#{$type}-left: $size * $spacing-base-size;
#{$type}-right: $size * $spacing-base-size;
}
.#{$typekey}y-#{$sizekey} {
#{$type}-top: $size * $spacing-base-size;
#{$type}-bottom: $size * $spacing-base-size;
}
}
//.mt-1
@each $directionkey, $direction in $spacing-directions {
@each $sizekey, $size in $spacing-sizes {
.#{$typekey}#{$directionkey}-#{$sizekey} {
#{$type}-#{$direction}: $size * $spacing-base-size;
}
}
}
.#{$typekey} {
#{$type}: 0;
}
}

@ -0,0 +1,69 @@
<template>
<div :id="id" :class="className" :style="{ height: height, width: width }" />
</template>
<script>
import tdTheme from './theme.json' //
import '../map/fujian.js'
export default {
name: 'Echart',
props: {
className: {
type: String,
default: 'chart'
},
id: {
type: String,
default: 'chart'
},
width: {
type: String,
default: '100%'
},
height: {
type: String,
default: '2.5rem'
},
options: {
type: Object,
default: () => ({})
}
},
data() {
return {
chart: null
}
},
watch: {
options: {
handler(options) {
// trueechart
this.chart.setOption(options, true)
},
deep: true
}
},
mounted() {
this.$echarts.registerTheme('tdTheme', tdTheme) //
this.initChart()
},
beforeDestroy() {
this.chart.dispose()
this.chart = null
},
methods: {
initChart() {
// echart
this.chart = this.$echarts.init(this.$el, 'tdTheme')
//debugger
// this.chart = this.$echarts.init(this.$el, 'dark')
console.log(this.options)
this.chart.setOption(this.options, true)
}
}
}
</script>
<style>
</style>

@ -0,0 +1,490 @@
{
"color": [
"#2d8cf0",
"#19be6b",
"#ff9900",
"#E46CBB",
"#9A66E4",
"#ed3f14"
],
"backgroundColor": "rgba(0,0,0,0)",
"textStyle": {},
"title": {
"textStyle": {
"color": "#516b91"
},
"subtextStyle": {
"color": "#93b7e3"
}
},
"line": {
"itemStyle": {
"normal": {
"borderWidth": "2"
}
},
"lineStyle": {
"normal": {
"width": "2"
}
},
"symbolSize": "6",
"symbol": "emptyCircle",
"smooth": true
},
"radar": {
"itemStyle": {
"normal": {
"borderWidth": "2"
}
},
"lineStyle": {
"normal": {
"width": "2"
}
},
"symbolSize": "6",
"symbol": "emptyCircle",
"smooth": true
},
"bar": {
"itemStyle": {
"normal": {
"barBorderWidth": 0,
"barBorderColor": "#ccc"
},
"emphasis": {
"barBorderWidth": 0,
"barBorderColor": "#ccc"
}
}
},
"pie": {
"itemStyle": {
"normal": {
"borderWidth": 0,
"borderColor": "#ccc"
},
"emphasis": {
"borderWidth": 0,
"borderColor": "#ccc"
}
}
},
"scatter": {
"itemStyle": {
"normal": {
"borderWidth": 0,
"borderColor": "#ccc"
},
"emphasis": {
"borderWidth": 0,
"borderColor": "#ccc"
}
}
},
"boxplot": {
"itemStyle": {
"normal": {
"borderWidth": 0,
"borderColor": "#ccc"
},
"emphasis": {
"borderWidth": 0,
"borderColor": "#ccc"
}
}
},
"parallel": {
"itemStyle": {
"normal": {
"borderWidth": 0,
"borderColor": "#ccc"
},
"emphasis": {
"borderWidth": 0,
"borderColor": "#ccc"
}
}
},
"sankey": {
"itemStyle": {
"normal": {
"borderWidth": 0,
"borderColor": "#ccc"
},
"emphasis": {
"borderWidth": 0,
"borderColor": "#ccc"
}
}
},
"funnel": {
"itemStyle": {
"normal": {
"borderWidth": 0,
"borderColor": "#ccc"
},
"emphasis": {
"borderWidth": 0,
"borderColor": "#ccc"
}
}
},
"gauge": {
"itemStyle": {
"normal": {
"borderWidth": 0,
"borderColor": "#ccc"
},
"emphasis": {
"borderWidth": 0,
"borderColor": "#ccc"
}
}
},
"candlestick": {
"itemStyle": {
"normal": {
"color": "#edafda",
"color0": "transparent",
"borderColor": "#d680bc",
"borderColor0": "#8fd3e8",
"borderWidth": "2"
}
}
},
"graph": {
"itemStyle": {
"normal": {
"borderWidth": 0,
"borderColor": "#ccc"
}
},
"lineStyle": {
"normal": {
"width": 1,
"color": "#aaa"
}
},
"symbolSize": "6",
"symbol": "emptyCircle",
"smooth": true,
"color": [
"#2d8cf0",
"#19be6b",
"#f5ae4a",
"#9189d5",
"#56cae2",
"#cbb0e3"
],
"label": {
"normal": {
"textStyle": {
"color": "#eee"
}
}
}
},
"map": {
"itemStyle": {
"normal": {
"areaColor": "#f3f3f3",
"borderColor": "#516b91",
"borderWidth": 0.5
},
"emphasis": {
"areaColor": "rgba(165,231,240,1)",
"borderColor": "#516b91",
"borderWidth": 1
}
},
"label": {
"normal": {
"textStyle": {
"color": "#000"
}
},
"emphasis": {
"textStyle": {
"color": "rgb(81,107,145)"
}
}
}
},
"geo": {
"itemStyle": {
"normal": {
"areaColor": "#f3f3f3",
"borderColor": "#516b91",
"borderWidth": 0.5
},
"emphasis": {
"areaColor": "rgba(165,231,240,1)",
"borderColor": "#516b91",
"borderWidth": 1
}
},
"label": {
"normal": {
"textStyle": {
"color": "#000"
}
},
"emphasis": {
"textStyle": {
"color": "rgb(81,107,145)"
}
}
}
},
"categoryAxis": {
"axisLine": {
"show": true,
"lineStyle": {
"color": "#cccccc"
}
},
"axisTick": {
"show": false,
"lineStyle": {
"color": "#333"
}
},
"axisLabel": {
"show": true,
"textStyle": {
"color": "#fff"
}
},
"splitLine": {
"show": false,
"lineStyle": {
"color": [
"#eeeeee"
]
}
},
"splitArea": {
"show": false,
"areaStyle": {
"color": [
"rgba(250,250,250,0.05)",
"rgba(200,200,200,0.02)"
]
}
}
},
"valueAxis": {
"axisLine": {
"show": true,
"lineStyle": {
"color": "#cccccc"
}
},
"axisTick": {
"show": false,
"lineStyle": {
"color": "#333"
}
},
"axisLabel": {
"show": true,
"textStyle": {
"color": "#fff"
}
},
"splitLine": {
"show": false,
"lineStyle": {
"color": [
"#eeeeee"
]
}
},
"splitArea": {
"show": false,
"areaStyle": {
"color": [
"rgba(250,250,250,0.05)",
"rgba(200,200,200,0.02)"
]
}
}
},
"logAxis": {
"axisLine": {
"show": true,
"lineStyle": {
"color": "#cccccc"
}
},
"axisTick": {
"show": false,
"lineStyle": {
"color": "#333"
}
},
"axisLabel": {
"show": true,
"textStyle": {
"color": "#999999"
}
},
"splitLine": {
"show": true,
"lineStyle": {
"color": [
"#eeeeee"
]
}
},
"splitArea": {
"show": false,
"areaStyle": {
"color": [
"rgba(250,250,250,0.05)",
"rgba(200,200,200,0.02)"
]
}
}
},
"timeAxis": {
"axisLine": {
"show": true,
"lineStyle": {
"color": "#cccccc"
}
},
"axisTick": {
"show": false,
"lineStyle": {
"color": "#333"
}
},
"axisLabel": {
"show": true,
"textStyle": {
"color": "#999999"
}
},
"splitLine": {
"show": true,
"lineStyle": {
"color": [
"#eeeeee"
]
}
},
"splitArea": {
"show": false,
"areaStyle": {
"color": [
"rgba(250,250,250,0.05)",
"rgba(200,200,200,0.02)"
]
}
}
},
"toolbox": {
"iconStyle": {
"normal": {
"borderColor": "#999"
},
"emphasis": {
"borderColor": "#666"
}
}
},
"legend": {
"textStyle": {
"color": "#fff"
}
},
"tooltip": {
"axisPointer": {
"lineStyle": {
"color": "#ccc",
"width": 1
},
"crossStyle": {
"color": "#ccc",
"width": 1
}
}
},
"timeline": {
"lineStyle": {
"color": "#8fd3e8",
"width": 1
},
"itemStyle": {
"normal": {
"color": "#8fd3e8",
"borderWidth": 1
},
"emphasis": {
"color": "#8fd3e8"
}
},
"controlStyle": {
"normal": {
"color": "#8fd3e8",
"borderColor": "#8fd3e8",
"borderWidth": 0.5
},
"emphasis": {
"color": "#8fd3e8",
"borderColor": "#8fd3e8",
"borderWidth": 0.5
}
},
"checkpointStyle": {
"color": "#8fd3e8",
"borderColor": "rgba(138,124,168,0.37)"
},
"label": {
"normal": {
"textStyle": {
"color": "#8fd3e8"
}
},
"emphasis": {
"textStyle": {
"color": "#8fd3e8"
}
}
}
},
"visualMap": {
"color": [
"#516b91",
"#59c4e6",
"#a5e7f0"
]
},
"dataZoom": {
"backgroundColor": "rgba(0,0,0,0)",
"dataBackgroundColor": "rgba(255,255,255,0.3)",
"fillerColor": "rgba(167,183,204,0.4)",
"handleColor": "#a7b7cc",
"handleSize": "100%",
"textStyle": {
"color": "#333"
}
},
"markPoint": {
"label": {
"normal": {
"textStyle": {
"color": "#eee"
}
},
"emphasis": {
"textStyle": {
"color": "#eee"
}
}
}
}
}

File diff suppressed because one or more lines are too long

@ -0,0 +1,71 @@
<template>
<div>
<!-- 设备利用率 -->
<Echart
id="bottomLeftChart"
:options="options"
height="190px"
width="100%"
style="margin-top:5px"
/>
</div>
</template>
<script>
import Echart from '@/common/echart'
export default {
components: {
Echart
},
props: {
cdata: {
type: Object,
default: () => ({})
}
},
data() {
return {
options: {}
}
},
watch: {
cdata: {
handler(newData) {
this.options = {
tooltip: {
trigger: 'axis',
axisPointer: {
// Use axis to trigger tooltip
type: 'shadow' // 'shadow' as default; can also be 'line' or 'shadow'
}
},
legend: {},
grid: {
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true
},
xAxis: {
type: 'category',
data: newData.xAxis.data
},
yAxis: {
type: 'value'
},
series: newData.series,
//
// label: {
// show: true
// },
emphasis: {
focus: 'series'
}
}
},
immediate: true,
deep: true
}
}
}
</script>

@ -0,0 +1,121 @@
<template>
<div>
<Chart :cdata="cdata" />
</div>
</template>
<script>
import Chart from './chart.vue'
import { request } from '@/utils/request.js'
export default {
components: {
Chart
},
data() {
return {
id: '',
cdata: {
'xAxis': {
'data': [
'05-21',
'05-22',
'05-23',
'05-24',
'05-25',
'05-26',
'05-27'
]
},
'series': [
{
'name': '设备1',
'type': 'bar',
'emphasis': {
'focus': 'series'
},
'data': [
320, 332, 301, 334, 390, 330, 320
]
},
{
'name': '设备2',
'type': 'bar',
'emphasis': {
'focus': 'series'
},
'data': [
120, 132, 101, 134, 90, 230, 210
]
},
{
'name': '设备3',
'type': 'bar',
'emphasis': {
'focus': 'series'
},
'data': [
120, 132, 101, 134, 90, 230, 210
]
},
{
'name': '设备4',
'type': 'bar',
'emphasis': {
'focus': 'series'
},
'data': [
150, 232, 201, 154, 190, 330, 410
]
}
]
}
}
},
mounted() {
this.setData()
this.startInterval()
},
methods: {
//
startInterval() {
const _this = this
// 10s
const time = 10 * 60 * 1000
if (this.intervalId !== null) {
clearInterval(this.intervalId)
}
this.intervalId = setInterval(() => {
_this.setData()
}, time)
},
//
setData() {
const _this = this
request({
// api
url: '/api/BigScreen/getMonthData',
method: 'get'
}).then(r => {
// debugger
// console.log(r.data.ProductQty)
// if (r) {
// _this.cdata = r.data.ProductQty
// }
if (r) {
_this.cdata = r.data.ProductQty
this.cdata.series.forEach(i => {
i.type = 'bar'
i.emphasis = {
focus: 'series'
}
})
}
})
}
}
}
</script>
<style lang="scss" scoped>
</style>

@ -0,0 +1,58 @@
<template>
<div>
<Echart
id="centreLeft1Chart"
:options="options"
height="230px"
width="105%"
/>
</div>
</template>
<script>
import Echart from '@/common/echart'
export default {
components: {
Echart
},
props: {
cdata: {
type: Object,
default: () => ({})
}
},
data() {
return {
options: {}
}
},
watch: {
cdata: {
handler(newData) {
//console.log(newData)
this.options = {
xAxis: {
type: 'category',
data: newData.xAxis.data
},
yAxis: {
type: 'value'
},
series: newData.series
//
// label: {
// position: 'top',
// show: true,
// textStyle: { //
// fontSize: 14
// }
// }
}
},
immediate: true,
deep: true
}
}
}
</script>

@ -0,0 +1,116 @@
<template>
<div>
<Chart :cdata="cdata" />
</div>
</template>
<script>
import Chart from "./chart.vue";
import { request } from "@/utils/request.js";
export default {
components: {
Chart,
},
data() {
return {
drawTiming: null,
cdata: {
xAxis: {
type: "category",
data: ["Mon1", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"],
},
yAxis: {
type: "value",
},
series: [
{
data: [820, 932, 901, 934, 90, 330, 130],
type: "bar",
smooth: true,
},
],
},
};
},
mounted() {
this.startInterval();
this.setData();
},
methods: {
//
startInterval() {
const _this = this;
// 10s
const time = 10 * 60 * 1000;
if (this.intervalId !== null) {
clearInterval(this.intervalId);
}
this.intervalId = setInterval(() => {
_this.setData();
}, time);
},
//
setData() {
const _this = this;
request({
// api
url: "/api/BigScreen/getMonthData",
method: "get",
}).then((r) => {
// debugger
if (r) {
_this.cdata = r.data.EqmtRate;
console.log("zzzzzzzzzzzzz");
console.log(this.cdata);
// this.cdata.xAxis.data = [
// ...this.cdata.xAxis.data,
// "5#",
// "7#",
// "8#",
// "20#",
// "21#",
// ];
this.cdata.series.forEach((i) => {
// i.data = [...i.data, 0, 0, 0, 0, 0];
i.data.map((item, index, self) => {
i.data[index] = Math.trunc(item);
});
i.type = "bar";
i.markLine = {
focus: "series",
};
i.label = {
show: true, //
position: "top", //
textStyle: {
//
color: "white",
fontSize: 14,
},
};
var colorList = [];
for (const item of i.data) {
if (item > 85) {
colorList.push("#19BB65");
} else {
colorList.push("red");
}
}
i.itemStyle = {
color: function (params) {
if (params.dataIndex >= colorList.length) {
params.dataIndex = params.dataIndex - colorList.length;
}
return colorList[params.dataIndex];
},
};
});
}
});
},
},
};
</script>
<style lang="scss" scoped>
</style>

@ -0,0 +1,140 @@
<template>
<div>
<!-- 合格率-->
<Echart
:id="id"
:options="options"
height="150px"
width="120px"
/>
</div>
</template>
<script>
import Echart from '@/common/echart'
export default {
components: {
Echart
},
props: {
id: {
type: String,
required: true,
default: 'chartRate'
},
tips: {
type: Number,
required: true,
default: 50
},
colorObj: {
type: Object,
default: function() {
return {
textStyle: '#3fc0fb',
series: {
color: ['#00bcd44a', 'transparent'],
dataColor: {
normal: '#03a9f4',
shadowColor: '#97e2f5'
}
}
}
}
}
},
data() {
return {
options: {}
}
},
watch: {
// tips
tips: {
handler(newData) {
debugger
this.options = {
series: [
{
type: 'gauge',
// radius: '20%' | 100,
arcLineWidth: 200,
progress: {
show: true,
width: 18
},
axisLine: {
lineStyle: {
width: 18
}
},
axisTick: {
show: false
},
splitLine: {
// show: false,
length: 10,
lineStyle: {
width: 2,
color: '#555'
}
},
axisLabel: {
show: false,
distance: 50,
color: '#999',
fontSize: 10
},
anchor: {
show: true,
showAbove: true,
size: 25,
itemStyle: {
borderWidth: 50
}
},
title: {
show: true
},
detail: {
valueAnimation: true,
fontSize: 20,
offsetCenter: [0, '100%']
},
data: [
{
lineWidth: 100,
value: newData
// name: 'sfsefe '
}
]
}
// {
// name: 'Pressure',
// type: 'gauge',
// progress: {
// show: true
// },
// detail: {
// valueAnimation: true,
// formatter: '{value}'
// },
// data: [
// {
// value: newData
// // name: 'SCORE'
// }
// ]
// }
]
}
},
immediate: true,
deep: true
}
}
}
</script>
<style lang="scss" scoped>
</style>

@ -0,0 +1,81 @@
<template>
<div>
<Echart
id="centreLeft1Chart"
:options="options"
height="220px"
width="260px"
/>
</div>
</template>
<script>
import Echart from '@/common/echart'
export default {
components: {
Echart
},
props: {
cdata: {
type: Object,
default: () => ({})
}
},
data() {
return {
options: {}
}
},
watch: {
cdata: {
handler(newData) {
this.options = {
color: [
'#37a2da',
'#32c5e9',
'#9fe6b8',
'#ffdb5c',
'#ff9f7f',
'#fb7293',
'#e7bcf3',
'#8378ea'
],
tooltip: {
trigger: 'item',
formatter: '{a} <br/>{b} : {c} ({d}%)'
},
toolbox: {
show: true
},
calculable: true,
legend: {
orient: 'horizontal',
icon: 'circle',
bottom: 0,
x: 'center',
data: newData.xData,
textStyle: {
color: '#fff'
}
},
series: [
{
name: '通过率统计',
type: 'pie',
radius: [10, 50],
roseType: 'area',
center: ['50%', '40%'],
data: newData.seriesData
}
]
}
},
immediate: true,
deep: true
}
}
}
</script>
<style lang="scss" scoped>
</style>

@ -0,0 +1,36 @@
<template>
<div>
<Chart :cdata="cdata" />
</div>
</template>
<script>
import Chart from './chart.vue'
export default {
components: {
Chart
},
data() {
return {
cdata: {
xData: ['data1', 'data2', 'data3', 'data4', 'data5', 'data6'],
seriesData: [
{ value: 10, name: 'data1' },
{ value: 5, name: 'data2' },
{ value: 15, name: 'data3' },
{ value: 25, name: 'data4' },
{ value: 20, name: 'data5' },
{ value: 35, name: 'data6' }
]
}
}
},
mounted() {
},
methods: {
}
}
</script>
<style lang="scss" scoped>
</style>

@ -0,0 +1,290 @@
<template>
<div>
<Echart
id="centreLeft2Chart"
ref="centreLeft2ChartRef"
:options="options"
height="360px"
width="330px"
/>
</div>
</template>
<script>
import Echart from '@/common/echart'
export default {
components: {
Echart
},
props: {
cdata: {
type: Array,
default: () => []
}
},
data() {
return {
options: {}
}
},
watch: {
cdata: {
handler(newData) {
// ()
const geoCoordMap = {
厦门市: [118.11022, 24.490474, 20],
福州市: [119.206239, 26.275302, 20],
泉州市: [118.589421, 24.908853, 20],
漳州市: [117.561801, 24.510897, 20],
龙岩市: [116.82978, 25.391603, 20],
莆田市: [119.007558, 25.591011, 20],
三明市: [117.435001, 26.465444, 20],
南平市: [118.178459, 27.535627, 20],
宁德市: [119.527082, 27.15924, 20]
}
const seriesData = [
{
name: '厦门市'
},
{
name: '福州市'
},
{
name: '泉州市'
},
{
name: '漳州市'
},
{
name: '龙岩市'
},
{
name: '莆田市'
},
{
name: '三明市'
},
{
name: '南平市'
},
{
name: '宁德市'
}
]
const convertData = function(data) {
const scatterData = []
for (var i = 0; i < data.length; i++) {
var geoCoord = geoCoordMap[data[i].name]
if (geoCoord) {
scatterData.push({
name: data[i].name,
value: geoCoord.concat(data[i].value)
})
}
}
return scatterData
}
this.options = {
showLegendSymbol: true,
tooltip: {
trigger: 'item',
textStyle: {
fontSize: 14,
lineHeight: 22
},
position: point => {
//
return [point[0] + 50, point[1] - 20]
}
// tooltip使formatter
/*
formatter: params => {
return `<div style=""> ... </div>`
}
*/
},
visualMap: {
min: 0,
max: 10,
show: false,
seriesIndex: 0,
//
inRange: {
color: ['rgba(41,166,206, .5)', 'rgba(69,117,245, .9)']
}
},
//
geo: {
show: true,
aspectScale: 0.85, //
zoom: 1.2,
top: '10%',
left: '16%',
map: '福建',
roam: false,
itemStyle: {
normal: {
areaColor: 'rgba(0,0,0,0)',
shadowColor: 'rgba(7,114,204, .8)',
shadowOffsetX: 5,
shadowOffsetY: 5
},
emphasis: {
areaColor: '#00aeef'
}
}
},
series: [
{
name: '相关指数',
type: 'map',
aspectScale: 0.85, //
zoom: 1.2,
mapType: '福建', //
top: '10%',
left: '16%',
itemStyle: {
normal: {
color: 'red',
areaColor: 'rgba(19,54,162, .5)',
borderColor: 'rgba(0,242,252,.3)',
borderWidth: 1,
shadowBlur: 7,
shadowColor: '#00f2fc'
},
emphasis: {
areaColor: '#4f7fff',
borderColor: 'rgba(0,242,252,.6)',
borderWidth: 2,
shadowBlur: 10,
shadowColor: '#00f2fc'
}
},
label: {
formatter: params => `${params.name}`,
show: true,
position: 'insideRight',
textStyle: {
fontSize: 14,
color: '#efefef'
},
emphasis: {
textStyle: {
color: '#fff'
}
}
},
data: newData
},
{
type: 'effectScatter',
coordinateSystem: 'geo',
symbolSize: 7,
effectType: 'ripple',
legendHoverLink: false,
showEffectOn: 'render',
rippleEffect: {
period: 4,
scale: 2.5,
brushType: 'stroke'
},
zlevel: 1,
itemStyle: {
normal: {
color: '#99FBFE',
shadowBlur: 5,
shadowColor: '#fff'
}
},
data: convertData(seriesData)
}
]
}
//
this.handleMapRandomSelect()
},
immediate: true,
deep: true
}
},
methods: {
//
startInterval() {
const _self = this
// 5s
const time = 2000
if (this.intervalId !== null) {
clearInterval(this.intervalId)
}
this.intervalId = setInterval(() => {
_self.reSelectMapRandomArea()
}, time)
},
//
reSelectMapRandomArea() {
const length = 9
this.$nextTick(() => {
try {
const map = this.$refs.centreLeft2ChartRef.chart
let index = Math.floor(Math.random() * length)
while (index === this.preSelectMapIndex || index >= length) {
index = Math.floor(Math.random() * length)
}
map.dispatchAction({
type: 'mapUnSelect',
seriesIndex: 0,
dataIndex: this.preSelectMapIndex
})
map.dispatchAction({
type: 'showTip',
seriesIndex: 0,
dataIndex: index
})
map.dispatchAction({
type: 'mapSelect',
seriesIndex: 0,
dataIndex: index
})
this.preSelectMapIndex = index
} catch (error) {
console.log(error)
}
})
},
handleMapRandomSelect() {
this.$nextTick(() => {
try {
const map = this.$refs.centreLeft2ChartRef.chart
const _self = this
setTimeout(() => {
_self.reSelectMapRandomArea()
}, 0)
//
map.on('mouseover', function(params) {
clearInterval(_self.intervalId)
map.dispatchAction({
type: 'mapUnSelect',
seriesIndex: 0,
dataIndex: _self.preSelectMapIndex
})
map.dispatchAction({
type: 'mapSelect',
seriesIndex: 0,
dataIndex: params.dataIndex
})
_self.preSelectMapIndex = params.dataIndex
})
//
map.on('globalout', function() {
_self.reSelectMapRandomArea()
_self.startInterval()
})
this.startInterval()
} catch (error) {
console.log(error)
}
})
}
}
}
</script>

@ -0,0 +1,67 @@
<template>
<div>
<Chart :cdata="cdata" />
</div>
</template>
<script>
import Chart from './chart.vue'
export default {
components: {
Chart
},
data() {
return {
cdata: [
{
// common/map/fujian.js
name: '福州市',
value: 10,
elseData: {
// tooltip
}
},
{
name: '厦门市',
value: 9
},
{
name: '漳州市',
value: 8
},
{
name: '泉州市',
value: 7
},
{
name: '三明市',
value: 6
},
{
name: '莆田市',
value: 5
},
{
name: '南平市',
value: 4
},
{
name: '龙岩市',
value: 3
},
{
name: '宁德市',
value: 2
}
]
}
},
mounted() {
},
methods: {
}
}
</script>
<style lang="scss" scoped>
</style>

@ -0,0 +1,132 @@
<template>
<div>
<Echart
id="centreRight2Chart1"
:options="options"
height="200px"
width="260px"
/>
</div>
</template>
<script>
import Echart from '@/common/echart'
export default {
components: {
Echart
},
props: {
cdata: {
type: Object,
default: () => ({})
}
},
data() {
return {
options: {}
}
},
watch: {
cdata: {
handler(newData) {
//
const lineStyle = {
normal: {
width: 1,
opacity: 0.5
}
}
this.options = {
radar: {
indicator: newData.indicatorData,
shape: 'circle',
splitNumber: 5,
radius: ['0%', '65%'],
name: {
textStyle: {
color: 'rgb(238, 197, 102)'
}
},
splitLine: {
lineStyle: {
color: [
'rgba(238, 197, 102, 0.1)',
'rgba(238, 197, 102, 0.2)',
'rgba(238, 197, 102, 0.4)',
'rgba(238, 197, 102, 0.6)',
'rgba(238, 197, 102, 0.8)',
'rgba(238, 197, 102, 1)'
].reverse()
}
},
splitArea: {
show: false
},
axisLine: {
lineStyle: {
color: 'rgba(238, 197, 102, 0.5)'
}
}
},
series: [
{
name: '北京',
type: 'radar',
lineStyle: lineStyle,
data: newData.dataBJ,
symbol: 'none',
itemStyle: {
normal: {
color: '#F9713C'
}
},
areaStyle: {
normal: {
opacity: 0.1
}
}
},
{
name: '上海',
type: 'radar',
lineStyle: lineStyle,
data: newData.dataSH,
symbol: 'none',
itemStyle: {
normal: {
color: '#B3E4A1'
}
},
areaStyle: {
normal: {
opacity: 0.05
}
}
},
{
name: '广州',
type: 'radar',
lineStyle: lineStyle,
data: newData.dataGZ,
symbol: 'none',
itemStyle: {
normal: {
color: 'rgb(238, 197, 102)'
}
},
areaStyle: {
normal: {
opacity: 0.05
}
}
} // end
]
}
},
immediate: true,
deep: true
}
}
}
</script>

@ -0,0 +1,55 @@
<template>
<div>
<Chart :cdata="cdata" />
</div>
</template>
<script>
import Chart from './chart.vue'
export default {
components: {
Chart
},
data() {
return {
cdata: {
indicatorData: [
{ name: 'data1', max: 300 },
{ name: 'data2', max: 250 },
{ name: 'data3', max: 300 },
{ name: 'data4', max: 5 },
{ name: 'data5', max: 200 },
{ name: 'data6', max: 100 }
],
dataBJ: [
[94, 69, 114, 2.08, 73, 39, 22],
[99, 73, 110, 2.43, 76, 48, 23],
[31, 12, 30, 0.5, 32, 16, 24],
[42, 27, 43, 1, 53, 22, 25],
[154, 117, 157, 3.05, 92, 58, 26],
[234, 185, 230, 4.09, 123, 69, 27],
[160, 120, 186, 2.77, 91, 50, 28]
],
dataGZ: [
[84, 94, 140, 2.238, 68, 18, 22],
[93, 77, 104, 1.165, 53, 7, 23],
[99, 130, 227, 3.97, 55, 15, 24],
[146, 84, 139, 1.094, 40, 17, 25],
[113, 108, 137, 1.481, 48, 15, 26],
[81, 48, 62, 1.619, 26, 3, 27],
[56, 48, 68, 1.336, 37, 9, 28]
],
dataSH: [
[91, 45, 125, 0.82, 34, 23, 1],
[65, 27, 78, 0.86, 45, 29, 2],
[83, 60, 84, 1.09, 73, 27, 3],
[109, 81, 121, 1.28, 68, 51, 4],
[106, 77, 114, 1.07, 55, 51, 5],
[109, 81, 121, 1.28, 68, 51, 6],
[106, 77, 114, 1.07, 55, 51, 7]
]
}
}
}
}
</script>

@ -0,0 +1,37 @@
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import dataV from '@jiaminghi/data-view'
// 引入全局css
import './assets/scss/style.scss'
// 按需引入vue-awesome图标
import Icon from 'vue-awesome/components/Icon'
import 'vue-awesome/icons/chart-bar.js'
import 'vue-awesome/icons/chart-area.js'
import 'vue-awesome/icons/chart-pie.js'
import 'vue-awesome/icons/chart-line.js'
import 'vue-awesome/icons/align-left.js'
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
// 引入echart
// 4.x 引用方式
// import echarts from 'echarts'
// 5.x 引用方式为按需引用
// 希望使用5.x版本的话,需要在package.json中更新版本号,并切换引用方式
import * as echarts from 'echarts'
Vue.prototype.$echarts = echarts
Vue.config.productionTip = false
// 全局注册
Vue.component('icon', Icon)
Vue.use(dataV)
Vue.use(ElementUI)
new Vue({
router,
store,
render: (h) => h(App)
}).$mount('#app')

@ -0,0 +1,15 @@
import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)
const routes = [{
path: '/',
name: 'index',
component: () => import('../views/index.vue')
}]
const router = new VueRouter({
routes
})
export default router

@ -0,0 +1,15 @@
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
},
mutations: {
},
actions: {
},
modules: {
}
})

@ -0,0 +1 @@
测试加密

@ -0,0 +1,57 @@
// 屏幕适配 mixin 函数
// * 默认缩放值
const scale = {
width: '1',
height: '1'
}
// * 设计稿尺寸px
const baseWidth = 1920
const baseHeight = 1080
// * 需保持的比例默认1.77778
const baseProportion = parseFloat((baseWidth / baseHeight).toFixed(5))
export default {
data() {
return {
// * 定时函数
drawTiming: null
}
},
mounted() {
this.calcRate()
window.addEventListener('resize', this.resize)
},
beforeDestroy() {
window.removeEventListener('resize', this.resize)
},
methods: {
calcRate() {
const appRef = this.$refs['appRef']
if (!appRef) return
// 当前宽高比
const currentRate = parseFloat((window.innerWidth / window.innerHeight).toFixed(5))
if (appRef) {
if (currentRate > baseProportion) {
// 表示更宽
scale.width = ((window.innerHeight * baseProportion) / baseWidth).toFixed(5)
scale.height = (window.innerHeight / baseHeight).toFixed(5)
appRef.style.transform = `scale(${scale.width}, ${scale.height}) translate(-50%, -50%)`
} else {
// 表示更高
scale.height = ((window.innerWidth / baseProportion) / baseHeight).toFixed(5)
scale.width = (window.innerWidth / baseWidth).toFixed(5)
appRef.style.transform = `scale(${scale.width}, ${scale.height}) translate(-50%, -50%)`
}
}
},
resize() {
clearTimeout(this.drawTiming)
this.drawTiming = setTimeout(() => {
this.calcRate()
}, 200)
}
}
}

@ -0,0 +1,52 @@
/**
* @param {Function} fn 防抖函数
* @param {Number} delay 延迟时间
*/
export function debounce(fn, delay) {
var timer
return function() {
var context = this
var args = arguments
clearTimeout(timer)
timer = setTimeout(function() {
fn.apply(context, args)
}, delay)
}
}
/**
* @param {date} time 需要转换的时间
* @param {String} fmt 需要转换的格式 yyyy-MM-ddyyyy-MM-dd HH:mm:ss
*/
export function formatTime(time, fmt) {
if (!time) return ''
else {
const date = new Date(time)
const o = {
'M+': date.getMonth() + 1,
'd+': date.getDate(),
'H+': date.getHours(),
'm+': date.getMinutes(),
's+': date.getSeconds(),
'q+': Math.floor((date.getMonth() + 3) / 3),
S: date.getMilliseconds()
}
if (/(y+)/.test(fmt)) {
fmt = fmt.replace(
RegExp.$1,
(date.getFullYear() + '').substr(4 - RegExp.$1.length)
)
}
for (const k in o) {
if (new RegExp('(' + k + ')').test(fmt)) {
fmt = fmt.replace(
RegExp.$1,
RegExp.$1.length === 1
? o[k]
: ('00' + o[k]).substr(('' + o[k]).length)
)
}
}
return fmt
}
}

@ -0,0 +1,42 @@
import axios from 'axios'
import { BASE_URL, TIMEOUT } from './requestConfig'
const instance = axios.create({
baseURL: BASE_URL,
timeout: TIMEOUT
})
instance.interceptors.request.use(config => {
// 1.发送网络请求时, 在界面的中间位置显示Loading的组件
// 2.某一些请求要求用户必须携带token, 如果没有携带, 那么直接跳转到登录页面
// 3.params/data序列化的操作
// console.log('请求被拦截')
return config
}, err => {
console.log(err)
})
instance.interceptors.response.use(res => {
return res.data
}, err => {
if (err && err.response) {
switch (err.response.status) {
case 400:
console.log('请求错误')
break
case 401:
console.log('未授权访问')
break
default:
console.log('其他错误信息')
}
}
return err
})
// export default instance
export { instance as request }

@ -0,0 +1,8 @@
// const devBaseURL = 'http://localhost:5281'
// const devBaseURL = 'http://5a35a48943.wicp.vip:40709'
// const proBaseURL = 'http://5a35a48943.wicp.vip:40709'
const devBaseURL = 'http://222.71.165.187:9002'
const proBaseURL = 'http://222.71.165.187:9002'
export const BASE_URL = process.env.NODE_ENV === 'development' ? devBaseURL : proBaseURL
export const TIMEOUT = 5000

@ -0,0 +1,33 @@
// 混入代码 resize-mixins.js
// 改成 Scale 缩放之后,没有使用这个代码,但是保留
import { debounce } from '@/utils'
const resizeChartMethod = '$__resizeChartMethod'
export default {
data() {
// 在组件内部将图表 init 的引用映射到 chart 属性上
return {
chart: null
}
},
created() {
window.addEventListener('resize', this[resizeChartMethod], false)
},
activated() {
// 防止 keep-alive 之后图表变形
if (this.chart) {
this.chart.resize()
}
},
beforeDestroy() {
window.removeEventListener('reisze', this[resizeChartMethod])
},
methods: {
// 防抖函数来控制 resize 的频率
[resizeChartMethod]: debounce(function() {
if (this.chart) {
this.chart.resize()
}
}, 300)
}
}

Binary file not shown.

@ -0,0 +1,234 @@
<template>
<div id="bottomRight">
<div class="up">
<div
v-for="item in titleItem"
:key="item.title"
class="bg-color-black item"
>
<p class="ml-3 colorBlue fw-b fs-xl">{{ item.title }}</p>
<div>
<dv-digital-flop
class="dv-dig-flop ml-1 mt-2 pl-3"
:config="item.number"
/>
</div>
</div>
</div>
<div class="down">
<div class="percent">
<div class="item bg-color-black">
<span>设备利用率(%)</span>
<bottomRightChart />
</div>
</div>
<div class="ranking bg-color-black">
<span class="ranking_span">各产品合格率(%)</span>
<div class="item">
<div v-for="item in productOKRateList" :key="item.ProductName" class="ranking1">
<dv-water-level-pond :config="item.config" style="width:100px;height:70px" />
<span class="item_span">{{ item.ProductName }}</span>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import bottomRightChart from '@/components/echart/bottom/bottomRightChart'
// import CenterChart from '@/components/echart/center/centerChartRate'
import { request } from '@/utils/request.js'
export default {
components: {
// CenterChart,
bottomRightChart
},
data() {
return {
water: {
data: [24, 45],
shape: 'roundRect',
formatter: '{value}%',
waveNum: 3
},
productOKRateList: [],
config: {
data: [10],
shape: 'round',
waveHeight: 10,
waveNum: 2,
colors: ['#00FFFF', '#00B2EE']
},
//
rate: [
{
id: 'centerRate1',
tips: 60,
colorData: {
textStyle: '#3fc0fb',
series: {
color: ['#00bcd44a', 'transparent'],
dataColor: {
normal: '#03a9f4',
shadowColor: '#97e2f5'
}
}
}
},
{
id: 'centerRate2',
tips: 40,
colorData: {
textStyle: '#67e0e3',
series: {
color: ['#faf3a378', 'transparent'],
dataColor: {
normal: '#ff9800',
shadowColor: '#fcebad'
}
}
}
}
]
}
},
mounted() {
this.startInterval()
this.setData()
},
methods: {
//
startInterval() {
const _this = this
// 10s
const time = 10 * 60 * 1000
if (this.intervalId !== null) {
clearInterval(this.intervalId)
}
this.intervalId = setInterval(() => {
_this.setData()
}, time)
},
//
setData() {
const _this = this
request({
// api
url: '/api/BigScreen/getMonthData',
method: 'get'
}).then(r => {
debugger
console.log(r.data.ProductOKRate)
if (r) {
debugger
const rData = r.data.ProductOKRate
_this.productOKRateList = []
for (const item of rData) {
var n = {
data: [item.OKRate],
shape: 'round',
formatter: '{value}%',
waveNum: 2,
waveHeight: 10,
// 97
colors: item.OKRate > 97 ? ['#00FFFF', '#00B2EE'] : ['#ff6600', '#cc0000']
}
_this.productOKRateList.push({
ProductName: item.ProductName,
config: n
})
}
}
})
}
}
}
</script>
<style lang="scss" scoped>
#bottomRight {
display: flex;
flex-direction: column;
.up {
width: 100%;
display: flex;
flex-wrap: wrap;
justify-content: space-around;
.item {
border-radius: 6px;
padding-top: 8px;
margin-top: 8px;
width: 32%;
height: 70px;
.dv-dig-flop {
width: 150px;
height: 30px;
}
}
}
.down {
margin: 10px;
padding: 10px;
width: 100%;
display: flex;
height: 245px;
justify-content: space-between;
.bg-color-black {
border-radius: 5px;
}
.ranking {
width: 59%;
padding-left:10px;
.ranking_span{
margin-top: 15px;
font-size: 16px;
display: flex;
justify-content: center;
}
.item {
margin-top: 10px;
display: flex;
flex-wrap: wrap;
}
.item_span{
margin:25px;
}
}
.ranking1{
margin-left:20px;
}
.percent {
width: 40%;
display: flex;
flex-wrap: wrap;
.item {
width: 100%;
height: 225px;
span {
margin-top: 15px;
font-size: 16px;
display: flex;
justify-content: center;
}
}
.water {
width: 100%;
.dv-wa-le-po {
height: 120px;
}
}
}
}
}
</style>

@ -0,0 +1,245 @@
<template>
<div id="center">
<div class="up">
<div
v-for="item in titleItem"
:key="item.title"
class="bg-color-black item"
>
<p class="ml-3 colorBlue fw-b fs-xl">{{ item.title }}</p>
<div>
<dv-digital-flop
class="dv-dig-flop ml-1 mt-2 pl-3"
:config="item.number"
/>
</div>
</div>
</div>
<div class="down">
<div class="percent">
<div class="item bg-color-black">
<span>生产订单达成率</span>
<dv-water-level-pond :config="config" style="width:100px;height:100px" />
<!-- <CenterChart
:id="rate[0].id"
:tips="rate[0].tips"
:color-obj="rate[0].colorData"
/> -->
</div>
<div class="item bg-color-black">
<span>订单交付率</span>
<dv-water-level-pond :config="config1" style="width:100px;height:100px" />
<!-- <CenterChart
:id="rate[1].id"
:tips="rate[1].tips"
:color-obj="rate[1].colorData"
/> -->
</div>
</div>
<div class="ranking bg-color-black">
<span>各产品生产数量</span>
<BottomLeftChart />
</div>
</div>
</div>
</template>
<script>
// import CenterChart from '@/components/echart/center/centerChartRate/index'
import BottomLeftChart from '@/components/echart/bottom/bottomLeftChart'
import { request } from '@/utils/request.js'
export default {
components: {
// CenterChart,
BottomLeftChart
},
data() {
return {
config: {
data: [10],
shape: 'round',
waveHeight: 10,
waveNum: 2
// colors: ['#003366', 'FFE4C4']
},
config1: {
data: [10],
shape: 'round',
waveHeight: 10,
waveNum: 2
// colors: ['#003366', 'FFE4C4']
},
water: {
data: [24, 45],
shape: 'roundRect',
formatter: '{value}%',
waveNum: 3
},
//
rate: [
{
id: 'centerRate1',
tips: 60,
colorData: {
textStyle: '#3fc0fb',
series: {
color: ['#00bcd44a', 'transparent'],
dataColor: {
normal: '#03a9f4',
shadowColor: '#97e2f5'
}
}
}
},
{
id: 'centerRate2',
tips: 40,
colorData: {
textStyle: '#67e0e3',
series: {
color: ['#faf3a378', 'transparent'],
dataColor: {
normal: '#ff9800',
shadowColor: '#fcebad'
}
}
}
}
]
}
},
mounted() {
this.startInterval()
this.setData()
},
methods: {
//
startInterval() {
const _this = this
// 10s
const time = 10 * 60 * 1000
if (this.intervalId !== null) {
clearInterval(this.intervalId)
}
this.intervalId = setInterval(() => {
_this.setData()
}, time)
},
//
setData() {
const _this = this
request({
// api
url: '/api/BigScreen/getMonthData',
method: 'get'
}).then(r => {
console.log(r.data.MoCompleteRate)
if (r) {
debugger
// _this.config.data[0] = r.data.MoCompleteRate
_this.config = {
data: [r.data.MoCompleteRate],
shape: 'round',
waveHeight: 10,
waveNum: 2
// colors: ['#003366', 'FFE4C4']
}
_this.config1 = {
data: [r.data.PoCompleteRate],
shape: 'round',
waveHeight: 10,
waveNum: 2
// colors: ['#003366', 'FFE4C4']
}
}
// if (r) {
// _this.cdata = r.data.EqmtRate
// this.cdata.series.forEach(i => {
// i.type = 'line'
// i.markLine = {
// focus: 'series'
// }
// })
// }
})
}
}
}
</script>
<style lang="scss" scoped>
#center {
display: flex;
flex-direction: column;
.up {
width: 100%;
display: flex;
flex-wrap: wrap;
justify-content: space-around;
.item {
border-radius: 6px;
padding-top: 8px;
margin-top: 8px;
width: 32%;
height: 70px;
.dv-dig-flop {
width: 150px;
height: 30px;
}
}
}
.down {
margin: 10px;
padding: 10px;
width: 100%;
display: flex;
height: 245px;
justify-content: space-between;
.bg-color-black {
border-radius: 5px;
}
.ranking {
padding: 15px;
width: 59%;
text-align: center;
padding-bottom: 10px;
.dv-scr-rank-board {
height: 180px;
}
span{
margin-top: 20px;
}
}
.percent {
width: 40%;
display: flex;
flex-wrap: wrap;
.item {
padding-left: 35px;
width: 50%;
height: 225px;
span {
// margin:30px 10px 40px 30px;
margin-top:15px;
margin-left: 10px;
margin-bottom: 50px;
font-size: 16px;
display: flex;
/*justify-content: center;*/
}
}
.water {
width: 100%;
.dv-wa-le-po {
height: 120px;
}
}
}
}
}
</style>

@ -0,0 +1,387 @@
<template>
<div id="centerLeft1">
<div v-for="item in reqlist" :key="item.eqmt_name" class="bg-color-black">
<div class="d-flex pt-2 pl-2">
<!-- <div class="text1">
<p style="width:60px">{{ item.eqmt_name }}</p>
</div> -->
<div class="text2">
<p style="width:100px;height:37px;">{{ item.eqmt_name }}</p>
<dv-water-level-pond
:config="item.config"
style="width: 100px; height: 100px"
/>
<span>产线合格率</span>
</div>
<div class="text3">
<p>
产品类型<span>{{ item.product_type_name }}</span>
</p>
<p>
当日合格数量<span>{{ item.intraday_ok_qty }}</span>
</p>
<p>
OEE<span>{{ item.oee }}</span>
</p>
<p>
停机次数<span>{{ item.intraday_eqmt_stop_times }}</span>
</p>
</div>
</div>
</div>
<div v-for="index in lessL" :key="index" class="bg-color-black">
<div class="d-flex pt-2 pl-2">
</div>
</div>
</div>
</template>
<script>
import { request } from "@/utils/request.js";
export default {
components: {},
data() {
return {
lessL: 0,
reqlist: [],
config: {
data: [10],
shape: "round",
waveHeight: 2,
waveNum: 2,
// colors: ['#003366', 'FFE4C4']
},
cdata: [
{
type: "gauge",
progress: {
show: true,
width: 18,
},
axisLine: {
lineStyle: {
width: 18,
},
},
axisTick: {
show: false,
},
splitLine: {
length: 15,
lineStyle: {
width: 2,
color: "#555",
},
},
axisLabel: {
distance: 25,
color: "#999",
fontSize: 20,
},
anchor: {
show: true,
showAbove: true,
size: 25,
itemStyle: {
borderWidth: 10,
},
},
title: {
show: true,
},
detail: {
valueAnimation: true,
fontSize: 80,
offsetCenter: [0, "20%"],
},
data: [
{
value: 20,
name: "sfsefe ",
},
],
},
],
};
},
mounted() {
this.setData();
this.startInterval();
},
methods: {
//
startInterval() {
const _this = this;
// 10s
const time = 10 * 60 * 1000;
if (this.intervalId !== null) {
clearInterval(this.intervalId);
}
this.intervalId = setInterval(() => {
_this.setData();
}, time);
},
// //
setData() {
const _this = this;
request({
// 线
url: "/api/BigScreen/getEqmtDetailList",
method: "get",
}).then((r) => {
debugger;
if (r) {
const rData = r.data;
let objS = [
{
collect_id: null,
create_time: null,
eqmt_alarm_flag: 0,
eqmt_except_flag: 0,
eqmt_id: 0,
eqmt_name: "5#",
eqmt_status: 0,
gmt_create: "2022-08-30 08:16:52",
gmt_modified: null,
id: 0,
intraday_eqmt_run_time: 0,
intraday_eqmt_stop_time: 0,
intraday_eqmt_stop_times: 0,
intraday_eqmt_work_rate: 0,
intraday_eqmt_work_time: 0,
intraday_ng_qty: 0,
intraday_ok_qty: 0,
intraday_product_qty: 0,
intraday_yield_rate: 0,
oee: 0,
product_type: null,
product_type_name: null,
speed: 0,
sys_org_code: null,
total_product_qty: 0,
update_by: null,
update_time: null,
},
{
collect_id: null,
create_time: null,
eqmt_alarm_flag: 0,
eqmt_except_flag: 0,
eqmt_id: 0,
eqmt_name: "7#",
eqmt_status: 0,
gmt_create: "2022-08-30 08:16:52",
gmt_modified: null,
id: 0,
intraday_eqmt_run_time: 0,
intraday_eqmt_stop_time: 0,
intraday_eqmt_stop_times: 0,
intraday_eqmt_work_rate: 0,
intraday_eqmt_work_time: 0,
intraday_ng_qty: 0,
intraday_ok_qty: 0,
intraday_product_qty: 0,
intraday_yield_rate: 0,
oee: 0,
product_type: null,
product_type_name: null,
speed: 0,
sys_org_code: null,
total_product_qty: 0,
update_by: null,
update_time: null,
},
{
collect_id: null,
create_time: null,
eqmt_alarm_flag: 0,
eqmt_except_flag: 0,
eqmt_id: 0,
eqmt_name: "8#",
eqmt_status: 0,
gmt_create: "2022-08-30 08:16:52",
gmt_modified: null,
id: 0,
intraday_eqmt_run_time: 0,
intraday_eqmt_stop_time: 0,
intraday_eqmt_stop_times: 0,
intraday_eqmt_work_rate: 0,
intraday_eqmt_work_time: 0,
intraday_ng_qty: 0,
intraday_ok_qty: 0,
intraday_product_qty: 0,
intraday_yield_rate: 0,
oee: 0,
product_type: null,
product_type_name: null,
speed: 0,
sys_org_code: null,
total_product_qty: 0,
update_by: null,
update_time: null,
},
{
collect_id: null,
create_time: null,
eqmt_alarm_flag: 0,
eqmt_except_flag: 0,
eqmt_id: 0,
eqmt_name: "20#",
eqmt_status: 0,
gmt_create: "2022-08-30 08:16:52",
gmt_modified: null,
id: 0,
intraday_eqmt_run_time: 0,
intraday_eqmt_stop_time: 0,
intraday_eqmt_stop_times: 0,
intraday_eqmt_work_rate: 0,
intraday_eqmt_work_time: 0,
intraday_ng_qty: 0,
intraday_ok_qty: 0,
intraday_product_qty: 0,
intraday_yield_rate: 0,
oee: 0,
product_type: null,
product_type_name: null,
speed: 0,
sys_org_code: null,
total_product_qty: 0,
update_by: null,
update_time: null,
},
{
collect_id: null,
create_time: null,
eqmt_alarm_flag: 0,
eqmt_except_flag: 0,
eqmt_id: 0,
eqmt_name: "21#",
eqmt_status: 0,
gmt_create: "2022-08-30 08:16:52",
gmt_modified: null,
id: 0,
intraday_eqmt_run_time: 0,
intraday_eqmt_stop_time: 0,
intraday_eqmt_stop_times: 0,
intraday_eqmt_work_rate: 0,
intraday_eqmt_work_time: 0,
intraday_ng_qty: 0,
intraday_ok_qty: 0,
intraday_product_qty: 0,
intraday_yield_rate: 0,
oee: 0,
product_type: null,
product_type_name: null,
speed: 0,
sys_org_code: null,
total_product_qty: 0,
update_by: null,
update_time: null,
}
];
const rData2 = [...rData];
//console.log(rData)
//rData = [...rData];
_this.reqlist = [];
for (const item of rData2) {
var n = {
data: [item.intraday_yield_rate],
shape: "round",
formatter: "{value}%",
waveNum: 2,
waveHeight: 10,
};
_this.reqlist.push({
eqmt_name: item.eqmt_name,
product_type_name: item.product_type_name,
intraday_ok_qty: item.intraday_ok_qty,
oee: item.oee,
intraday_eqmt_stop_times: item.intraday_eqmt_stop_times,
config: n,
});
}
this.lessL = 4 - rData2.length % 4
}
});
},
},
};
</script>
<style lang="scss" scoped>
$box-width: 980px;
$box-height: 210px;
#centerLeft1 {
display: grid;
grid-template-columns: repeat(3, 33%);
padding: 16px;
height: $box-height;
width: $box-width;
border-radius: 10px;
.bg-color-black {
height: $box-height - 0px;
border-radius: 10px;
}
.text {
color: #c3cbde;
}
.dv-dec-3 {
position: relative;
width: 100px;
height: 20px;
top: -3px;
}
.bottom-data {
.item-box {
& > div {
padding-right: 5px;
}
font-size: 14px;
float: right;
position: relative;
width: 50%;
color: #d3d6dd;
.dv-digital-flop {
width: 120px;
height: 30px;
}
//
.coin {
position: relative;
top: 6px;
font-size: 20px;
color: #ffc107;
}
.colorYellow {
color: yellowgreen;
}
p {
text-align: center;
}
}
}
}
.text2 {
margin-top: 10px;
margin-bottom: 20px;
line-height: 25px;
}
.text2 span {
margin: 10px;
}
.text1 p {
font-size: 18px;
}
.text3 {
margin-top: 37px;
margin-left: 20px;
height: 35px;
line-height: 35px;
}
</style>

@ -0,0 +1,326 @@
<template>
<div id="centerRight1">
<div class="bg-color-black">
<div class="d-flex pt-2 pl-2">
<span>
<!-- 图标-->
<!-- <icon name="chart-line" class="text-icon"></icon>-->
</span>
<div class="d-flex">
<!-- 标题-->
<!--<span class="fs-xl text mx-2">任务完成排行榜</span>-->
</div>
</div>
<div class="d-flex jc-center body-box">
<dv-scroll-board class="dv-scr-board" :config="config" @click="skipto" />
</div>
</div>
<el-dialog title="工单详细信息" style="font-color:#fff" :visible.sync="moDetailShow" width="50%" :append-to-body="true" @open="getmoDetailInfo">
<el-descriptions class="margin-top" :column="1" :size="size" border>
<el-descriptions-item>
<template slot="label">工单号</template>{{ moInfo.FBILL_NO }}
</el-descriptions-item>
<el-descriptions-item>
<template slot="label">产线</template>{{ moInfo.FWORK_SHOP }}
</el-descriptions-item>
<el-descriptions-item>
<template slot="label">产品名称</template>{{ moInfo.FMATERIAL_NAME }}
</el-descriptions-item>
<el-descriptions-item>
<template slot="label">型号</template>{{ moInfo.FSPECIFICATION }}
</el-descriptions-item>
<el-descriptions-item>
<template slot="label">单位</template>{{ moInfo.FUNIT_ID }}
</el-descriptions-item>
<el-descriptions-item>
<template slot="label">计划数量</template>{{ moInfo.FQTY_SHOW }}
</el-descriptions-item>
<el-descriptions-item>
<template slot="label">合格品数量</template>{{ moInfo.FREPQUAAUX_QTY_SHOW }}
</el-descriptions-item>
<el-descriptions-item>
<template slot="label">不合格数量</template>{{ moInfo.FREPFAILAUX_QTY_SHOW }}
</el-descriptions-item>
<el-descriptions-item>
<template slot="label">开工</template>{{ moInfo.FSTATUS }}
</el-descriptions-item>
<el-descriptions-item>
<template slot="label">计划开工日期</template>{{ moInfo.FPLAN_START_DATE_SHOW }}
</el-descriptions-item>
<el-descriptions-item>
<template slot="label">预定完工日期</template>{{ moInfo.FPLAN_FINISH_DATE_SHOW }}
</el-descriptions-item>
<el-descriptions-item>
<template slot="label">实际开工时间</template>{{ moInfo.FSTART_DATE_SHOW }}
</el-descriptions-item>
<el-descriptions-item>
<template slot="label">实际完工时间</template>{{ moInfo.FFINISH_DATE_SHOW }}
</el-descriptions-item>
</el-descriptions>
<span slot="footer" class="dialog-footer">
<el-button type="primary" @click="moDetailShow = false"> </el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import { request } from '@/utils/request.js'
export default {
data() {
return {
config: {
header: [
'生产工单',
'产品名称',
'计划数量',
'合格品数量',
'不合格数量',
'生产进度'
],
// data: [],
data: [
[
'组件1',
'dev-1',
"<span class='colorGrass'>↑75%</span>",
'dev-1',
'dev-1',
'dev-1'
],
[
'组件1',
'dev-1',
"<span class='colorGrass'>↑75%</span>",
'dev-1',
'dev-1',
'dev-1'
],
[
'组件1',
'dev-1',
"<span class='colorGrass'>↑75%</span>",
'dev-1',
'dev-1',
'dev-1'
],
[
'组件1',
'dev-1',
"<span class='colorGrass'>↑75%</span>",
'dev-1',
'dev-1',
'dev-1'
],
[
'组件1',
'dev-1',
"<span class='colorGrass'>↑75%</span>",
'dev-1',
'dev-1',
'dev-1'
],
[
'组件1',
'dev-1',
"<span class='colorGrass'>↑75%</span>",
'dev-1',
'dev-1',
'dev-1'
],
[
'组件1',
'dev-1',
"<span class='colorGrass'>↑75%</span>",
'dev-1',
'dev-1',
'dev-1'
],
[
'组件1',
'dev-1',
"<span class='colorGrass'>↑75%</span>",
'dev-1',
'dev-1',
'dev-1'
],
[
'组件1',
'dev-1',
"<span class='colorRed'>↑75%</span>",
'dev-1',
'dev-1',
'dev-1'
],
[
'组件1',
'dev-1',
"<span class='colorGrass'>↑75%</span>",
'dev-1',
'dev-1',
'dev-1'
],
[
'组件1',
'dev-1',
"<span class='colorGrass'>↑75%</span>",
'dev-1',
'dev-1',
'dev-1'
],
[
'组件1',
'dev-1',
"<span class='colorGrass'>↑75%</span>",
'dev-1',
'dev-1',
'dev-1'
]
],
rowNum: 8, //
align: ['center'],
headerHeight: 35,
headerBGC: '#0f1325', //
oddRowBGC: '#0f1325', //
evenRowBGC: '#171c33' //
/* index: true,
columnWidth: [50],
align: ['center']*/
},
moDetailShow: false,
moKey: null,
moInfo: {}
}
},
mounted() {
this.setData()
this.startInterval()
},
methods: {
//
skipto(config) {
debugger
// window.alert(config.row[6])
this.moKey = config.row[6]
this.moDetailShow = true
},
//
startInterval() {
const _this = this
const time = 1000 * 60 * 60 * 2
if (this.intervalId !== null) {
clearInterval(this.intervalId)
}
this.intervalId = setInterval(() => {
_this.setData()
}, time)
},
setData() {
const _this = this
request({
//
url: '/api/BigScreen/getPlanOrderList',
method: 'get'
}).then((r) => {
if (r) {
const newArr = r.data.map(function(item) {
var ret = []
ret.push(
item.FBILL_NO,
item.FMATERIAL_NAME,
item.FQTY_SHOW,
item.FREPQUAAUX_QTY_SHOW,
item.FREPFAILAUX_QTY_SHOW,
item.COMPLETE_RATE = (item.COMPLETE_RATE * 100).toFixed(1) + '%',
item.FENTRY_ID
)
return ret
})
_this.config = {
header: [
' 生产工单',
'产品名称',
'计划数量',
'合格数量',
'不合格数量',
'生产进度(%)',
'11'
],
data: newArr,
rowNum: 8, //
headerHeight: 35,
headerBGC: '#0f1325', //
oddRowBGC: '#0f1325', //
evenRowBGC: '#171c33', //
columnWidth: [110, 380, 100, 90, 100, 110, 0], //
align: ['left', 'left', 'right', 'right', 'right', 'right'] //
}
}
})
},
getmoDetailInfo() {
const _this = this
request({
//
url: '/api/BigScreen/getPlanOrderDetail?fentryId=' + this.moKey,
method: 'get'
}).then((r) => {
debugger
_this.moInfo = r.data
})
}
}
}
</script>
<style lang="scss" scoped>
$box-height: 350px;
$box-height: 350px;
$box-width: 900px;
#centerRight1 {
padding: 16px;
padding-top: 20px;
height: $box-height;
width: $box-width;
border-radius: 5px;
.bg-color-black {
height: $box-height - 30px;
border-radius: 10px;
}
.text {
color: #c3cbde;
}
/*内容的宽度和高度*/
.body-box {
border-radius: 10px;
overflow: hidden;
.dv-scr-board {
width: 900px;
height: 300px;
}
}
}
</style>
<style lang="scss">
.dv-scroll-board .header .header-item{
color: #00B2EE;
}
.el-dialog__header {
background-color:#f5f5f5 !important;
}
.el-dialog__body {
background-color:#f5f5f5 !important;
}
// .el-descriptions :not(.is-bordered) .el-descriptions-item__cell {
// background-color:#f5f5f5 !important;
// }
.el-dialog__footer {
background-color: #f5f5f5!important;
}
</style>

@ -0,0 +1,154 @@
<template>
<div id="index" ref="appRef">
<div class="bg">
<dv-loading v-if="loading">Loading...</dv-loading>
<div v-else class="host-body">
<!-- 头标-->
<div class="d-flex jc-center">
<dv-decoration-10 class="dv-dec-10" />
<div class="d-flex jc-center">
<dv-decoration-8 class="dv-dec-8" :color="decorationColor" />
<div class="title">
<!-- <span class="title-text">订单/设备综合信息看板</span> -->
<span class="title-text">生产智能化管理平台</span>
<dv-decoration-6
class="dv-dec-6"
:reverse="true"
:color="['#50e3c2', '#67a1e5']"
/>
</div>
<dv-decoration-8
class="dv-dec-8"
:reverse="true"
:color="decorationColor"
/>
</div>
<dv-decoration-10 class="dv-dec-10-s" />
</div>
<!-- 第二行 -->
<div class="d-flex jc-between px-2">
<div class="d-flex aside-width">
<div class="react-left ml-4 react-l-s">
<span class="react-left" />
<!-- <span class="text">数据分析1</span>-->
</div>
<div class="react-left ml-3">
<!-- <span class="text">数据分析2</span>-->
</div>
</div>
<div class="d-flex aside-width">
<div class="react-right bg-color-blue mr-3">
<span class="text fw-b">生产监控</span>
</div>
<div class="react-right mr-4 react-l-s">
<span class="react-after" />
<span class="text"
>{{ dateYear }} {{ dateWeek }} {{ dateDay }}</span
>
</div>
</div>
</div>
<div class="body-box">
<!-- 第三行数据 -->
<div class="content-box">
<!--左边数据显示-->
<div class="left-box">
<!--左边数据显示1-->
<div class="left-box-one">
<dv-border-box-12>
<centerRight1 />
</dv-border-box-12>
</div>
<!--左边数据显示2 动态月订单信息数据-->
<div class="left-box-two">
<!--生产订单 订单交付率 各产品生产数量-->
<dv-border-box-12>
<center />
</dv-border-box-12>
</div>
<div class="left-box-three">
<!--设备利用率(%) 各产品合格率-->
<dv-border-box-12>
<!--<center/>-->
<bottomRight />
</dv-border-box-12>
</div>
</div>
<!--右边数据显示-->
<div class="right-box">
<dv-border-box-12>
<center-left1 />
</dv-border-box-12>
</div>
</div>
</div>
<div class="bototm-box">
<span>Copyright © 上海长江云息数字科技有限公司版权所有</span>
</div>
</div>
</div>
</div>
</template>
<script>
import drawMixin from "../utils/drawMixin";
import { formatTime } from "../utils/index.js";
import centerRight1 from "./centerRight1";
import center from "./center";
import CenterLeft1 from "./centerLeft1";
import bottomRight from "./bottomRight";
export default {
components: {
CenterLeft1,
centerRight1,
center,
bottomRight,
},
mixins: [drawMixin],
data() {
return {
timing: null,
loading: true,
dateDay: null,
dateYear: null,
dateWeek: null,
weekday: ["周日", "周一", "周二", "周三", "周四", "周五", "周六"],
decorationColor: ["#568aea", "#000000"],
reqlist: [],
};
},
mounted() {
this.timeFn();
this.cancelLoading();
},
beforeDestroy() {
clearInterval(this.timing);
},
methods: {
timeFn() {
this.timing = setInterval(() => {
this.dateDay = formatTime(new Date(), "HH: mm: ss");
this.dateYear = formatTime(new Date(), "yyyy-MM-dd");
this.dateWeek = this.weekday[new Date().getDay()];
}, 1000);
},
cancelLoading() {
setTimeout(() => {
this.loading = false;
}, 500);
},
},
};
</script>
<style lang="scss" scoped>
@import "../assets/scss/index.scss";
.bototm-box {
width: 100%;
text-align: center;
margin-top: 20px;
}
</style>

@ -0,0 +1,12 @@
const path = require('path')
const resolve = dir => {
return path.join(__dirname, dir)
}
module.exports = {
publicPath: './',
lintOnSave: false,
chainWebpack: config => {
config.resolve.alias
.set('_c', resolve('src/components')) // key,value自行定义比如.set('@@', resolve('src/components'))
}
}

File diff suppressed because it is too large Load Diff
Loading…
Cancel
Save