Merge branch 'develop' of https://e.coding.net/ctcdevteam/hberp/hberp into develop

This commit is contained in:
shilixia 2022-01-27 15:53:40 +08:00
commit 290efe48ce
33 changed files with 3020 additions and 30 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 652 KiB

View File

@ -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,
);

View File

@ -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.jpg");
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-before {
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%);
}
}
}
}

View File

@ -0,0 +1,154 @@
@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;
}
}

View File

@ -0,0 +1,104 @@
<template>
<div>
<!-- 通过率/达标率 -->
<Echart
:options="options"
:id="id"
height="100px"
width="100px"
></Echart>
</div>
</template>
<script>
import Echart from './index'
export default {
data () {
return {
options: {},
};
},
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"
}
}
};
}
}
},
watch: {
// tips 是会变更的数据所以进行监听
tips: {
handler (newData) {
this.options = {
title:{
text: newData * 1 + "%",
x: "center",
y: "center",
textStyle: {
color: this.colorObj.textStyle,
fontSize: 16
}
},
series: [
{
type: "pie",
radius: ["75%", "80%"],
center: ["50%", "50%"],
hoverAnimation: false,
color: this.colorObj.series.color,
label: {
normal: {
show: false
}
},
data: [
{
value: newData,
itemStyle: {
normal: {
color: this.colorObj.series.dataColor.normal,
shadowBlur: 10,
shadowColor: this.colorObj.series.dataColor.shadowColor
}
}
},
{
value: 100 - newData
}
]
}
]
}
},
immediate: true,
deep: true
}
}
};
</script>
<style lang="scss" scoped>
</style>

View File

@ -0,0 +1,65 @@
<template>
<div :id="id" :class="className" :style="{ height: height, width: width }" />
</template>
<script>
import tdTheme from './theme.json' // 引入默认主题
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) {
// 设置true清空echart缓存
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')
this.chart.setOption(this.options, true)
}
}
}
</script>
<style>
</style>

View File

@ -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"
}
}
}
}
}

View File

@ -16,10 +16,15 @@ import router from './router'
import { plugin } from "vue-function-api";
import '@/icons' // icon
import '@/permission' // permission control
import tableHeight from '@/directive/el-table/index'
import tableHeight from '@/directive/el-table/index';
import echarts from 'echarts';
import dataV from '@jiaminghi/data-view';
// 引入全局css
import './assets/scss/style.scss';
Vue.component(CollapseTransition.name, CollapseTransition);
Vue.use(tableHeight).use(plugin);
Vue.prototype.$echarts = echarts;
Vue.use(dataV);
/**
* If you don't want to use mock-server
* you want to use MockJs for mock api

View File

@ -36,7 +36,6 @@ export const constantRoutes = [
component: () => import('@/views/login/index'),
hidden: true
},
{
path: '/404',
component: () => import('@/views/404'),
@ -53,6 +52,11 @@ export const constantRoutes = [
meta: { title: '首页', icon: 'dashboard', affix: true,keepAlive: false }
}]
},
{
path: '/index',
component: () => import('@/views/bigScreen/index'),
meta: { title: '大屏', icon: 'dashboard', affix: true,keepAlive: false }
},
{
path: '/changepassword',
component: Layout,

View File

@ -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)
}
},
}

View File

@ -382,3 +382,56 @@ const arrChange = arr => arr.map(item => {
}
return res
})
/**
* @param {Function} fn 防抖函数
* @param {Number} delay 延迟时间
*/
/*export function debounce(fn, delay) {
let timer;
return function () {
const context = this;
const 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 formatTimeBigScreen(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;
}
}

View File

@ -0,0 +1,32 @@
// 混入代码 resize-mixins.js
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),
},
};

View File

@ -0,0 +1,308 @@
<template>
<div id="bottomLeft">
<div class="bg-color-black">
<div class="d-flex pt-2 pl-2">
<span>
<el-icon class="el-icon-s-data"></el-icon>
</span>
<div class="d-flex">
<span class="fs-xl text mx-2">数据统计图</span>
</div>
</div>
<div>
<Echart
:options="options"
id="bottomLeftChart"
height="480px"
width="100%"
></Echart>
</div>
</div>
</div>
</template>
<script>
import Echart from '@/components/echart'
export default {
components: {
Echart
},
data() {
return {
options: {},
cdata: {
category: [
"市区",
"万州",
"江北",
"南岸",
"北碚",
"綦南",
"长寿",
"永川",
"璧山",
"江津",
"城口",
"大足",
"垫江",
"丰都",
"奉节",
"合川",
"江津区",
"开州",
"南川",
"彭水",
"黔江",
"石柱",
"铜梁",
"潼南",
"巫山",
"巫溪",
"武隆",
"秀山",
"酉阳",
"云阳",
"忠县",
"川东",
"检修"
],
lineData: [
18092,
20728,
24045,
28348,
32808,
36097,
39867,
44715,
48444,
50415,
56061,
62677,
59521,
67560,
18092,
20728,
24045,
28348,
32808,
36097,
39867,
44715,
48444,
50415,
36097,
39867,
44715,
48444,
50415,
50061,
32677,
49521,
32808
],
barData: [
4600,
5000,
5500,
6500,
7500,
8500,
9900,
12500,
14000,
21500,
23200,
24450,
25250,
33300,
4600,
5000,
5500,
6500,
7500,
8500,
9900,
22500,
14000,
21500,
8500,
9900,
12500,
14000,
21500,
23200,
24450,
25250,
7500
],
rateData: []
}
};
},
mounted() {
this.setData();
},
watch: {
cdata: {
handler(newData) {
this.options = {
title: {
text: "",
},
tooltip: {
trigger: "axis",
backgroundColor: "rgba(255,255,255,0.1)",
axisPointer: {
type: "shadow",
label: {
show: true,
backgroundColor: "#7B7DDC"
}
}
},
legend: {
data: ["已贯通", "计划贯通", "贯通率"],
textStyle: {
color: "#B4B4B4"
},
top: "0%"
},
grid: {
x: "8%",
width: "88%",
y: "4%"
},
xAxis: {
data: newData.category,
axisLine: {
lineStyle: {
color: "#B4B4B4"
}
},
axisTick: {
show: false
}
},
yAxis: [
{
splitLine: {show: false},
axisLine: {
lineStyle: {
color: "#B4B4B4"
}
},
axisLabel: {
formatter: "{value} "
}
},
{
splitLine: {show: false},
axisLine: {
lineStyle: {
color: "#B4B4B4"
}
},
axisLabel: {
formatter: "{value} "
}
}
],
series: [
{
name: "贯通率",
type: "line",
smooth: true,
showAllSymbol: true,
symbol: "emptyCircle",
symbolSize: 8,
yAxisIndex: 1,
itemStyle: {
normal: {
color: "#F02FC2"
}
},
data: newData.rateData
},
{
name: "已贯通",
type: "bar",
barWidth: 10,
itemStyle: {
normal: {
barBorderRadius: 5,
color: new this.$echarts.graphic.LinearGradient(0, 0, 0, 1, [
{offset: 0, color: "#956FD4"},
{offset: 1, color: "#3EACE5"}
])
}
},
data: newData.barData
},
{
name: "计划贯通",
type: "bar",
barGap: "-100%",
barWidth: 10,
itemStyle: {
normal: {
barBorderRadius: 5,
color: new this.$echarts.graphic.LinearGradient(0, 0, 0, 1, [
{offset: 0, color: "rgba(156,107,211,0.8)"},
{offset: 0.2, color: "rgba(156,107,211,0.5)"},
{offset: 1, color: "rgba(156,107,211,0.2)"}
])
}
},
z: -12,
data: newData.lineData
}
]
}
},
immediate: true,
deep: true
},
},
methods: {
// 根据自己的业务情况修改
setData() {
for (let i = 0; i < this.cdata.barData.length - 1; i++) {
let rate = this.cdata.barData[i] / this.cdata.lineData[i];
this.cdata.rateData.push(rate.toFixed(2));
}
},
}
}
</script>
<style lang="scss" scoped>
$box-height: 520px;
$box-width: 100%;
#bottomLeft {
padding: 20px 16px;
height: $box-height;
width: $box-width;
border-radius: 5px;
.bg-color-black {
height: $box-height - 35px;
border-radius: 10px;
}
.text {
color: #c3cbde;
}
.chart-box {
margin-top: 16px;
width: 170px;
height: 170px;
.active-ring-name {
padding-top: 10px;
}
}
}
</style>

View File

@ -0,0 +1,466 @@
<template>
<div id="bottomRight">
<div class="bg-color-black">
<div class="d-flex pt-2 pl-2">
<span>
<el-icon class="el-icon-s-marketing"></el-icon>
</span>
<div class="d-flex">
<span class="fs-xl text mx-2">工单修复以及满意度统计图</span>
<div class="decoration2">
<dv-decoration-2 :reverse="true" style="width:5px;height:6rem;" />
</div>
</div>
</div>
<div>
<Echart
:options="options"
id="centreLeft1Chart"
height="480px"
width="100%"
></Echart>
</div>
</div>
</div>
</template>
<script>
import Echart from '@/components/echart'
export default {
data () {
return {
drawTiming: null,
cdata: {
year: null,
weekCategory: [],
radarData: [],
radarDataAvg: [],
maxData: 12000,
weekMaxData: [],
weekLineData: []
},
options: {},
// 定义颜色
colorList: {
linearYtoG: {
type: "linear",
x: 0,
y: 0,
x2: 1,
y2: 1,
colorStops: [
{
offset: 0,
color: "#f5b44d"
},
{
offset: 1,
color: "#28f8de"
}
]
},
linearGtoB: {
type: "linear",
x: 0,
y: 0,
x2: 1,
y2: 0,
colorStops: [
{
offset: 0,
color: "#43dfa2"
},
{
offset: 1,
color: "#28f8de"
}
]
},
linearBtoG: {
type: "linear",
x: 0,
y: 0,
x2: 1,
y2: 0,
colorStops: [
{
offset: 0,
color: "#1c98e8"
},
{
offset: 1,
color: "#28f8de"
}
]
},
areaBtoG: {
type: "linear",
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [
{
offset: 0,
color: "rgba(35,184,210,.2)"
},
{
offset: 1,
color: "rgba(35,184,210,0)"
}
]
}
}
}
},
components: {
Echart
},
watch: {
cdata: {
handler (newData) {
this.options = {
title: {
text: "",
textStyle: {
color: "#D3D6DD",
fontSize: 24,
fontWeight: "normal"
},
subtext: newData.year + "/" + newData.weekCategory[6],
subtextStyle: {
color: "#fff",
fontSize: 16
},
top: 50,
left: 80
},
legend: {
top: 120,
left: 80,
orient: "vertical",
itemGap: 15,
itemWidth: 12,
itemHeight: 12,
data: ["平均指标", "我的指标"],
textStyle: {
color: "#fff",
fontSize: 14
}
},
tooltip: {
trigger: "item"
},
radar: {
center: ["68%", "27%"],
radius: "40%",
name: {
color: "#fff"
},
splitNumber: 8,
axisLine: {
lineStyle: {
color: this.colorList.linearYtoG,
opacity: 0.6
}
},
splitLine: {
lineStyle: {
color: this.colorList.linearYtoG,
opacity: 0.6
}
},
splitArea: {
areaStyle: {
color: "#fff",
opacity: 0.1,
shadowBlur: 25,
shadowColor: "#000",
shadowOffsetX: 0,
shadowOffsetY: 5
}
},
indicator: [
{
name: "服务态度",
max: newData.maxData
},
{
name: "产品质量",
max: 10
},
{
name: "任务效率",
max: 12
},
{
name: "售后保障",
max: 3.5
}
]
},
grid: {
left: 90,
right: 80,
bottom: 40,
top: "60%"
},
xAxis: {
type: "category",
position: "bottom",
axisLine: true,
axisLabel: {
color: "rgba(255,255,255,.8)",
fontSize: 12
},
data: newData.weekCategory
},
// 下方Y轴
yAxis: {
name: "工单",
nameLocation: "end",
nameGap: 24,
nameTextStyle: {
color: "rgba(255,255,255,.5)",
fontSize: 14
},
max: newData.maxData,
splitNumber: 4,
axisLine: {
lineStyle: {
opacity: 0
}
},
splitLine: {
show: true,
lineStyle: {
color: "#fff",
opacity: 0.1
}
},
axisLabel: {
color: "rgba(255,255,255,.8)",
fontSize: 12
}
},
series: [
{
name: "",
type: "radar",
symbolSize: 0,
data: [
{
value: newData.radarDataAvg[6],
name: "平均指标",
itemStyle: {
normal: {
color: "#f8d351"
}
},
lineStyle: {
normal: {
opacity: 0
}
},
areaStyle: {
normal: {
color: "#f8d351",
shadowBlur: 25,
shadowColor: "rgba(248,211,81,.3)",
shadowOffsetX: 0,
shadowOffsetY: -10,
opacity: 1
}
}
},
{
value: newData.radarData[6],
name: "我的指标",
itemStyle: {
normal: {
color: "#43dfa2"
}
},
lineStyle: {
normal: {
opacity: 0
}
},
areaStyle: {
normal: {
color: this.colorList.linearGtoB,
shadowBlur: 15,
shadowColor: "rgba(0,0,0,.2)",
shadowOffsetX: 0,
shadowOffsetY: 5,
opacity: 0.8
}
}
}
]
},
{
name: "",
type: "line",
smooth: true,
symbol: "emptyCircle",
symbolSize: 8,
itemStyle: {
normal: {
color: "#fff"
}
},
lineStyle: {
normal: {
color: this.colorList.linearBtoG,
width: 3
}
},
areaStyle: {
normal: {
color: this.colorList.areaBtoG
}
},
data: newData.weekLineData,
lineSmooth: true,
markLine: {
silent: true,
data: [
{
type: "average",
name: "平均值"
}
],
precision: 0,
label: {
normal: {
formatter: "平均值: \n {c}"
}
},
lineStyle: {
normal: {
color: "rgba(248,211,81,.7)"
}
}
},
tooltip: {
position: "top",
formatter: "{c} m",
backgroundColor: "rgba(28,152,232,.2)",
padding: 6
}
},
{
name: "占位背景",
type: "bar",
itemStyle: {
normal: {
show: true,
color: "#000",
opacity: 0
}
},
silent: true,
barWidth: "50%",
data: newData.weekMaxData,
animation: false
}
]
}
},
immediate: true,
deep: true
}
},
mounted () {
this.drawTimingFn();
},
beforeDestroy () {
clearInterval(this.drawTiming);
},
methods: {
drawTimingFn () {
this.setData();
this.drawTiming = setInterval(() => {
this.setData();
}, 6000);
},
setData () {
// 清空轮询数据
this.cdata.weekCategory = [];
this.cdata.weekMaxData = [];
this.cdata.weekLineData = [];
this.cdata.radarData = [];
this.cdata.radarDataAvg = [];
let dateBase = new Date();
this.cdata.year = dateBase.getFullYear();
// 周数据
for (let i = 0; i < 7; i++) {
// 日期
let date = new Date();
this.cdata.weekCategory.unshift([date.getMonth() + 1, date.getDate()-i].join("/"));
// 折线图数据
this.cdata.weekMaxData.push(this.cdata.maxData);
let distance = Math.round(Math.random() * 11000 + 500);
this.cdata.weekLineData.push(distance);
// 雷达图数据
// 我的指标
let averageSpeed = +(Math.random() * 5 + 3).toFixed(3);
let maxSpeed = averageSpeed + +(Math.random() * 3).toFixed(2);
let hour = +(distance / 1000 / averageSpeed).toFixed(1);
let radarDayData = [distance, averageSpeed, maxSpeed, hour];
this.cdata.radarData.unshift(radarDayData);
// 平均指标
let distanceAvg = Math.round(Math.random() * 8000 + 4000);
let averageSpeedAvg = +(Math.random() * 4 + 4).toFixed(3);
let maxSpeedAvg = averageSpeedAvg + +(Math.random() * 2).toFixed(2);
let hourAvg = +(distance / 1000 / averageSpeed).toFixed(1);
let radarDayDataAvg = [
distanceAvg,
averageSpeedAvg,
maxSpeedAvg,
hourAvg
];
this.cdata.radarDataAvg.unshift(radarDayDataAvg);
}
}
}
};
</script>
<style lang="scss" class>
$box-height: 520px;
$box-width: 100%;
#bottomRight {
padding: 14px 16px;
height: $box-height;
width: $box-width;
border-radius: 5px;
.bg-color-black {
height: $box-height - 30px;
border-radius: 10px;
}
.text {
color: #c3cbde;
}
//下滑线动态
.decoration2 {
position: absolute;
right: 0.125rem;
}
.chart-box {
margin-top: 16px;
width: 170px;
height: 170px;
.active-ring-name {
padding-top: 10px;
}
}
}
</style>

View File

@ -0,0 +1,271 @@
<template>
<div id="center">
<div class="up">
<div
class="bg-color-black item"
v-for="item in titleItem"
:key="item.title"
>
<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="ranking bg-color-black">
<span>
<el-icon class="el-icon-pie-chart"></el-icon>
</span>
<span class="fs-xl text mx-2 mb-1 pl-3">年度负责人组件达标榜</span>
<dv-scroll-ranking-board class="dv-scr-rank-board mt-1" :config="ranking" />
</div>
<div class="percent">
<div class="item bg-color-black">
<span>今日任务通过率</span>
<CenterChart
:id="rate[0].id"
:tips="rate[0].tips"
:colorObj="rate[0].colorData"
/>
</div>
<div class="item bg-color-black">
<span>今日任务达标率</span>
<CenterChart
:id="rate[1].id"
:tips="rate[1].tips"
:colorObj="rate[1].colorData"
/>
</div>
<div class="water">
<dv-water-level-pond class="dv-wa-le-po" :config="water" />
</div>
</div>
</div>
</div>
</template>
<script>
import CenterChart from '@/components/echart/chartRate.vue'
export default {
data() {
return {
titleItem: [
{
title: '今年累计合同数',
number: {
number: [12],//数字数值
toFixed: 0,//小数位数
textAlign: 'left',//水平对齐方式
content: '{nt}',//内容模版//rowGap行间距
style: {//样式配置
fontSize: 26
}
}
},
{
title: '本月累计订单数',
number: {
number: [12],
toFixed: 0,
textAlign: 'left',
content: '{nt}',
style: {
fontSize: 26
}
}
},
{
title: '今日在制任务数',
number: {
number: [2],
toFixed: 0,
textAlign: 'left',
content: '{nt}',
style: {
fontSize: 26
}
}
},
{
title: '本月累计交付产品数',
number: {
number: [8],
toFixed: 1,
textAlign: 'left',
content: '{nt}',
style: {
fontSize: 26
}
}
},
{
title: '今年成品合格率',
number: {
number: [96],
toFixed: 1,
textAlign: 'left',
content: '{nt}%',
style: {
fontSize: 26
}
}
},
{
title: '今年累计不合格产品数',
number: {
number: [2],
toFixed: 0,
textAlign: 'left',
content: '{nt}',
style: {
fontSize: 26
}
}
}
],
ranking: {
data: [
{
name: '冷加工',
value: 55
},
{
name: '热弯成型',
value: 120
},
{
name: '化学钢化',
value: 78
},
{
name: '镀膜',
value: 66
},
{
name: '夹层',
value: 80
},
{
name: '包边',
value: 80
},
{
name: '装框',
value: 80
}
],
carousel: 'single',
unit: '/件'
},
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'
}
}
}
}
]
}
},
components: {
CenterChart
}
}
</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 {
padding: 6px 4px;
padding-bottom: 0;
width: 100%;
display: flex;
height: 255px;
justify-content: space-between;
.bg-color-black {
border-radius: 5px;
}
.ranking {
padding: 10px;
width: 59%;
.dv-scr-rank-board {
height: 225px;
}
}
.percent {
width: 40%;
display: flex;
flex-wrap: wrap;
.item {
width: 50%;
height: 120px;
span {
margin-top: 8px;
font-size: 14px;
display: flex;
justify-content: center;
}
}
.water {
width: 100%;
.dv-wa-le-po {
height: 120px;
}
}
}
}
}
</style>

View File

@ -0,0 +1,242 @@
<template>
<div id="centerLeft1">
<div class="bg-color-black">
<div class="d-flex pt-2 pl-2">
<span>
<el-icon class="el-icon-s-help"></el-icon>
</span>
<div class="d-flex">
<span class="fs-xl text mx-2">任务通过率</span>
<dv-decoration-3 class="dv-dec-3"/>
</div>
</div>
<div class="d-flex jc-center">
<Echart
:options="options"
id="centreLeft1Chart"
height="220px"
width="260px"
></Echart>
</div>
<!-- 4个主要的数据 -->
<div class="bottom-data">
<div
class="item-box mt-2"
v-for="(item, index) in numberData"
:key="index"
>
<div class="d-flex">
<!--<span class="coin"></span>-->
<dv-digital-flop class="dv-digital-flop" :config="item.number"/>
</div>
<p class="text" style="text-align: center;">
{{ item.text }}
<span class="colorYellow">()</span>
</p>
</div>
</div>
</div>
</div>
</template>
<script>
import Echart from '@/components/echart'
export default {
data() {
return {
options: {},
numberData: [
{
number: {
number: [15],
toFixed: 1,
textAlign: 'left',
content: '{nt}',
style: {
fontSize: 24
}
},
text: '今日构建总量'
},
{
number: {
number: [1144],
toFixed: 1,
textAlign: 'left',
content: '{nt}',
style: {
fontSize: 24
}
},
text: '总共完成数量'
},
{
number: {
number: [361],
toFixed: 1,
textAlign: 'left',
content: '{nt}',
style: {
fontSize: 24
}
},
text: '正在编译数量'
},
{
number: {
number: [157],
toFixed: 1,
textAlign: 'left',
content: '{nt}',
style: {
fontSize: 24
}
},
text: '未通过数量'
}
],
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"}
]
}
}
},
components: {
Echart
},
mounted() {
this.changeTiming()
},
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
}
},
methods: {
changeTiming() {
setInterval(() => {
this.changeNumber()
}, 3000)
},
changeNumber() {
this.numberData.forEach((item, index) => {
item.number.number[0] += ++index
item.number = {...item.number}
})
}
}
}
</script>
<style lang="scss" scoped>
$box-width: 300px;
$box-height: 410px;
#centerLeft1 {
padding: 16px;
height: $box-height;
width: 100%;
border-radius: 10px;
.bg-color-black {
height: $box-height - 30px;
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;
}
}
}
}
</style>

View File

@ -0,0 +1,75 @@
<template>
<div id="centerRight1">
<div class="bg-color-black">
<div class="d-flex pt-2 pl-2">
<span>
<el-icon class="el-icon-s-operation"></el-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" />
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
config: {
header: ['姓名', '部门', '到岗'],
data: [
['组件1', 'dev-1', "<span class='colorGrass'>已到岗</span>"],
['组件2', 'dev-2', "<span class='colorRed'>未到岗</span>"],
['组件3', 'dev-3', "<span class='colorGrass'>已到岗</span>"],
['组件4', 'rea-1', "<span class='colorGrass'>已到岗</span>"],
['组件5', 'rea-2', "<span class='colorGrass'>已到岗</span>"],
['组件6', 'fix-2', "<span class='colorGrass'>已到岗</span>"],
['组件7', 'fix-4', "<span class='colorGrass'>已到岗</span>"],
['组件8', 'fix-7', "<span class='colorRed'>未到岗</span>"],
['组件9', 'dev-2', "<span class='colorRed'>未到岗</span>"],
['组件10', 'dev-9', "<span class='colorGrass'>已到岗</span>"]
],
rowNum: 7, //表格行数
headerHeight: 35,
headerBGC: '#0f1325', //表头
oddRowBGC: '#0f1325', //奇数行
evenRowBGC: '#171c33', //偶数行
index: true,
columnWidth: [50],
align: ['center']
}
}
}
}
</script>
<style lang="scss" scoped>
$box-height: 410px;
$box-width: 300px;
#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: 270px;
height: 340px;
}
}
}
</style>

View File

@ -0,0 +1,88 @@
<template>
<div id="centerRight2">
<div class="bg-color-black">
<div class="d-flex pt-2 pl-2">
<span>
<el-icon class="el-icon-menu"></el-icon>
</span>
<span class="fs-xl text mx-2">产品销售渠道分析</span>
</div>
<div class="d-flex ai-center flex-column body-box heightCover">
<dv-capsule-chart class="dv-cap-chart" :config="config" />
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
config: {
data: [
{
name: '冷加工',
value: 98
},
{
name: '热弯成型',
value: 100
},
{
name: '化学钢化',
value: 99
},
{
name: '镀膜',
value: 100
},
{
name: '夹层',
value: 98
},
{
name: '包边',
value: 100
},
{
name: '装框',
value: 100
}
]
}
}
},
}
</script>
<style lang="scss" scoped>
#centerRight2 {
$box-height: 410px;
$box-width: 340px;
padding: 5px;
height: $box-height;
width: $box-width;
border-radius: 5px;
.bg-color-black {
padding: 5px;
height: $box-height;
width: $box-width;
border-radius: 10px;
}
.text {
color: #c3cbde;
}
.body-box {
border-radius: 10px;
overflow: hidden;
.dv-cap-chart {
width: 100%;
height: 90%;
}
}
.heightCover{
height: 100%;
}
}
</style>

View File

@ -0,0 +1,148 @@
<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="['#568aea', '#000000']" />
<div class="title">
<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="['#568aea', '#000000']"
/>
</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-before"></span>
<span class="text">数据分析1</span>
</div>
<div class="react-right 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>
<span class="text"
>{{ dateYear }} {{ dateWeek }} {{ dateDay }}</span
>
</div>
</div>
</div>
<div class="body-box">
<!-- 第三行数据 -->
<div class="content-box">
<div>
<dv-border-box-1>
<centerLeft1 />
</dv-border-box-1>
</div>
<div>
<dv-border-box-1>
<centerLeft1 />
</dv-border-box-1>
</div>
<!-- 中间 -->
<div>
<center />
</div>
<!-- 中间 -->
<div>
<centerRight2 />
</div>
<div>
<dv-border-box-13>
<centerRight1 />
</dv-border-box-13>
</div>
</div>
<!-- 第四行数据 -->
<div class="bototm-box">
<dv-border-box-3>
<bottomRight />
</dv-border-box-3>
<dv-border-box-13>
<bottomLeft />
</dv-border-box-13>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import drawMixin from "../../utils/drawMixin";
import { formatTimeBigScreen } from '../../utils/index.js'
import centerLeft1 from './centerLeft1'
import centerRight1 from './centerRight1'
import centerRight2 from './centerRight2'
import center from './center'
import bottomLeft from './bottomLeft'
import bottomRight from './bottomRight'
export default {
mixins: [ drawMixin ],
data() {
return {
timing: null,
loading: true,
dateDay: null,
dateYear: null,
dateWeek: null,
weekday: ['周日', '周一', '周二', '周三', '周四', '周五', '周六']
}
},
components: {
centerLeft1,
centerRight1,
centerRight2,
center,
bottomLeft,
bottomRight
},
mounted() {
this.timeFn()
this.cancelLoading()
},
beforeDestroy () {
clearInterval(this.timing)
},
methods: {
timeFn() {
this.timing = setInterval(() => {
this.dateDay = formatTimeBigScreen(new Date(), 'HH: mm: ss')
this.dateYear = formatTimeBigScreen(new Date(), 'yyyy-MM-dd')
this.dateWeek = this.weekday[new Date().getDay()]
}, 1000)
},
cancelLoading() {
setTimeout(() => {
this.loading = false
}, 500)
}
}
}
</script>
<style lang="scss">
@import '../../assets/scss/index';
</style>

View File

@ -10,6 +10,8 @@ from django.db.models.query import Prefetch
class EmployeeSerializer(DynamicFieldsSerializerMixin, ModelSerializer):
name = serializers.CharField(source='user.name', read_only=True)
dept_ = OrganizationSimpleSerializer(source='user.dept', read_only=True)
is_atwork = serializers.BooleanField(source='user.is_atwork', read_only=True)
last_check_time = serializers.DateTimeField(source='user.last_check_time', read_only=True)
class Meta:
model = Employee
exclude = ['face_data']

View File

@ -0,0 +1,20 @@
# Generated by Django 3.2.9 on 2022-01-27 07:47
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('pum', '0004_puorder_puorderitem'),
('inm', '0028_alter_fifoitem_files'),
]
operations = [
migrations.AddField(
model_name='fifo',
name='pu_order',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='pum.puorder', verbose_name='关联采购订单'),
),
]

View File

@ -2,6 +2,7 @@ from django.db import models
from django.db.models.base import Model
import django.utils.timezone as timezone
from django.db.models.query import QuerySet
from apps.pum.models import PuOrder
from apps.system.models import CommonADModel, CommonAModel, CommonBModel, Organization, User, Dict, File
from utils.model import SoftModel, BaseModel
from simple_history.models import HistoricalRecords
@ -78,6 +79,8 @@ class FIFO(CommonADModel):
User, verbose_name='审核人', on_delete=models.CASCADE, null=True, blank=True)
inout_date = models.DateField('出入库日期', null=True, blank=True)
remark = models.CharField('备注', max_length=1000, default='')
pu_order = models.ForeignKey(PuOrder, verbose_name='关联采购订单',
null=True, blank=True, on_delete=models.CASCADE)
class FIFOItem(BaseModel):

View File

@ -0,0 +1,53 @@
# Generated by Django 3.2.9 on 2022-01-27 07:47
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
import django.utils.timezone
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('mtm', '0044_subproduction_need_combtest'),
('pum', '0003_remove_vendor_material'),
]
operations = [
migrations.CreateModel(
name='PuOrder',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('create_time', models.DateTimeField(default=django.utils.timezone.now, help_text='创建时间', verbose_name='创建时间')),
('update_time', models.DateTimeField(auto_now=True, help_text='修改时间', verbose_name='修改时间')),
('is_deleted', models.BooleanField(default=False, help_text='删除标记', verbose_name='删除标记')),
('number', models.CharField(max_length=100, unique=True, verbose_name='订单编号')),
('is_audited', models.BooleanField(default=False, verbose_name='是否审核')),
('create_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='puorder_create_by', to=settings.AUTH_USER_MODEL, verbose_name='创建人')),
('update_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='puorder_update_by', to=settings.AUTH_USER_MODEL, verbose_name='最后编辑人')),
('vendor', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='pum.vendor', verbose_name='供应商')),
],
options={
'verbose_name': '采购订单',
'verbose_name_plural': '采购订单',
},
),
migrations.CreateModel(
name='PuOrderItem',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('create_time', models.DateTimeField(default=django.utils.timezone.now, help_text='创建时间', verbose_name='创建时间')),
('update_time', models.DateTimeField(auto_now=True, help_text='修改时间', verbose_name='修改时间')),
('is_deleted', models.BooleanField(default=False, help_text='删除标记', verbose_name='删除标记')),
('count', models.PositiveIntegerField(default=0, verbose_name='所需数量')),
('delivered_count', models.PositiveIntegerField(default=0, verbose_name='已到货数量')),
('delivery_date', models.DateField(verbose_name='截止到货日期')),
('material', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='mtm.material', verbose_name='采购材料')),
('pu_order', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='item_pu_order', to='pum.puorder', verbose_name='关联采购订单')),
],
options={
'abstract': False,
},
),
]

View File

@ -5,7 +5,7 @@ from django.db.models.query import QuerySet
from apps.system.models import CommonAModel, CommonBModel, Organization, User, Dict, File
from utils.model import SoftModel, BaseModel
from simple_history.models import HistoricalRecords
from apps.mtm.models import Material
class Vendor(CommonAModel):
@ -23,4 +23,26 @@ class Vendor(CommonAModel):
verbose_name_plural = verbose_name
def __str__(self):
return self.name
return self.name
class PuOrder(CommonAModel):
"""
采购订单信息
"""
number = models.CharField('订单编号', max_length=100, unique=True)
vendor = models.ForeignKey(Vendor, verbose_name='供应商', on_delete=models.CASCADE)
is_audited = models.BooleanField('是否审核', default=False)
class Meta:
verbose_name = '采购订单'
verbose_name_plural = verbose_name
class PuOrderItem(BaseModel):
"""
采购具体项目
"""
material = models.ForeignKey(Material, verbose_name='采购材料', on_delete=models.CASCADE)
count = models.PositiveIntegerField('所需数量', default=0)
delivered_count = models.PositiveIntegerField('已到货数量', default=0)
delivery_date = models.DateField('截止到货日期')
pu_order = models.ForeignKey(PuOrder, verbose_name='关联采购订单',
on_delete=models.CASCADE, null=True, blank=True, related_name='item_pu_order')

View File

@ -1,9 +1,31 @@
from rest_framework.serializers import ModelSerializer
from .models import Vendor
from apps.mtm.serializers import MaterialSimpleSerializer
from .models import PuOrder, PuOrderItem, Vendor
class VendorSerializer(ModelSerializer):
class Meta:
model = Vendor
fields = '__all__'
class VendorSimpleSerializer(ModelSerializer):
class Meta:
model = Vendor
fields = ['id', 'name']
class PuOrderItemSerializer(ModelSerializer):
material_ = MaterialSimpleSerializer(source='material', read_only=True)
class Meta:
model = PuOrderItem
fields = '__all__'
class PuOrderSerializer(ModelSerializer):
vendor_ = VendorSimpleSerializer(source='vendor', read_only=True)
items = PuOrderItemSerializer(source='item_pu_order', many=True, read_only=True)
class Meta:
model = PuOrder
fields = '__all__'
class PuOrderCreateUpdateSerializer(ModelSerializer):
class Meta:
fields = ['number', 'vendor']

View File

@ -1,8 +1,10 @@
from django.shortcuts import render
from rest_framework.viewsets import ModelViewSet
from apps.pum.models import Vendor
from apps.pum.serializers import VendorSerializer
from rest_framework.mixins import CreateModelMixin, DestroyModelMixin
from rest_framework.viewsets import GenericViewSet
from apps.pum.models import PuOrder, Vendor
from apps.pum.serializers import PuOrderCreateUpdateSerializer, PuOrderSerializer, VendorSerializer
from apps.system.mixins import CreateUpdateModelAMixin, OptimizationMixin
@ -19,3 +21,27 @@ class VendorViewSet(CreateUpdateModelAMixin, ModelViewSet):
filterset_fields = []
ordering_fields = ['create_time']
ordering = ['-create_time']
class PuOrderViewSet(CreateUpdateModelAMixin, ModelViewSet):
"""
采购订单-增删改查
"""
perms_map = {'get': '*', 'post': '*',
'put': '*', 'delete': '*'}
queryset = PuOrder.objects.select_related('vendor').\
prefetch_related('item_pu_order').all()
serializer_class = PuOrderSerializer
search_fields = ['number', 'vendor__name']
filterset_fields = ['vendor']
ordering = ['-create_time']
def get_serializer_class(self):
if self.action in ['create', 'update']:
return PuOrderCreateUpdateSerializer
return super().get_serializer_class()
class PuOrderItemViewSet(CreateModelMixin, DestroyModelMixin, GenericViewSet):
pass

View File

@ -0,0 +1,18 @@
# Generated by Django 3.2.9 on 2022-01-27 07:47
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('sam', '0011_order_need_mtest'),
]
operations = [
migrations.AlterField(
model_name='order',
name='delivery_date',
field=models.DateField(verbose_name='截止交货日期'),
),
]

View File

@ -58,7 +58,7 @@ class Order(CommonAModel):
count = models.PositiveIntegerField('所需数量', default=0)
planed_count = models.PositiveIntegerField('已排数量', default=0)
delivered_count = models.PositiveIntegerField('已交货数量', default=0)
delivery_date = models.DateField('交货日期')
delivery_date = models.DateField('截止交货日期')
need_mtest = models.BooleanField('是否需要军检', default=False)
class Meta:
verbose_name = '订单信息'

View File

@ -1,5 +1,6 @@
from django.shortcuts import render
from numpy import number
from rest_framework import serializers
from rest_framework.generics import ListAPIView, CreateAPIView
from rest_framework.views import APIView
@ -78,10 +79,11 @@ class AtWorkCountView(CreateAPIView):
serializer.is_valid(raise_exception=True)
vdata = serializer.validated_data
ret = ClockRecord.objects.filter(
create_time__year = vdata['year'],
create_time__month = vdata['month']
update_time__year = vdata['year'],
update_time__month = vdata['month']
).values(
user_id = F('create_by'),
number = F('create_by__employee_user__number'),
username = F('create_by__username'),
name = F('create_by__name'),
dept_name = F('create_by__dept__name')).annotate(

View File

@ -137,14 +137,14 @@ class UserListSerializer(DynamicFieldsSerializerMixin, serializers.ModelSerializ
"""
用户列表序列化
"""
dept_name = serializers.StringRelatedField(source='dept')
roles_name = serializers.StringRelatedField(source='roles', many=True)
dept_ = OrganizationSimpleSerializer(source='dept', read_only=True)
roles_ = RoleSerializer(source='roles', many=True)
class Meta:
model = User
fields = ['id', 'name', 'phone', 'email', 'position',
'username', 'is_active', 'date_joined',
'dept_name', 'dept', 'roles', 'avatar',
'roles_name', 'is_atwork', 'last_check_time']
'dept_', 'dept', 'roles', 'avatar',
'roles_', 'is_atwork', 'last_check_time']
@staticmethod
def setup_eager_loading(queryset):

View File

@ -261,7 +261,7 @@ class UserViewSet(ModelViewSet):
# 根据请求类型动态变更serializer
if self.action == 'create':
return UserCreateSerializer
elif self.action == 'list':
elif self.action in ['list', 'retrieve']:
return UserListSerializer
return UserModifySerializer

View File

@ -11,3 +11,4 @@ psutil==5.8.0
pillow==8.3.1
opencv-python==4.5.3.56
django-celery-results==2.2.0
numpy==1.21.2

View File

@ -1,3 +1,4 @@
import os
from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework.parsers import MultiPartParser
@ -6,10 +7,9 @@ from PIL import Image
from django.conf import settings
from rest_framework import status
from datetime import datetime
import os
import uuid
import cv2
from server.settings import BASE_DIR
import numpy as np
# class UploadFileView(APIView):
# permission_classes = [IsAuthenticated]
@ -39,16 +39,33 @@ class GenSignature(APIView):
def post(self, request, *args, **kwargs):
path = (BASE_DIR + request.data['path']).replace('\\', '/')
image = cv2.imread(path, cv2.IMREAD_UNCHANGED)
size = image.shape
for i in range(size[0]):
for j in range(size[1]):
if image[i][j][0]>100 and image[i][j][1]>100 and image[i][j][2]>100:
image[i][j][3] = 0
else:
image[i][j][0],image[i][j][1],image[i][j][2] = 0,0,0
cv2.imwrite(path,image)
return Response(request.data, status=status.HTTP_200_OK)
try:
image = cv2.imread(path, cv2.IMREAD_UNCHANGED)
size = image.shape
width = size[0] # 宽度
height = size[1] # 高度
if size[2] != 4: # 判断
background = np.zeros((size[0], size[1], 4))
for yh in range(height):
for xw in range(width):
background[xw, yh, :3] = image[xw, yh]
background[xw, yh, 3] = 255
image = background
size = image.shape
for i in range(size[0]):
for j in range(size[1]):
if image[i][j][0]>100 and image[i][j][1]>100 and image[i][j][2]>100:
image[i][j][3] = 0
else:
image[i][j][0],image[i][j][1],image[i][j][2] = 0,0,0
ext = os.path.splitext(path)
new_path = ext[0] + '.png'
cv2.imwrite(new_path, image)
return Response({'path':new_path.replace(BASE_DIR, '')}, status=status.HTTP_200_OK)
except:
return Response('签名照处理失败,请重新上传',
status=status.HTTP_400_BAD_REQUEST)
import time
class UpdateDevelop(APIView):