Commit a3d1c564 authored by 张牧越's avatar 张牧越

数字工地 实名制页面完成

parent 786d7acb
module.exports = {
root: true,
env: {
node: true
},
'extends': [
'plugin:vue/essential',
'eslint:recommended'
],
parserOptions: {
parser: '@babel/eslint-parser'
},
rules: {
'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
//在rules中添加自定义规则
//关闭组件命名规则
"vue/multi-word-component-names": "off",
},
overrides: [
{
files: [
'**/__tests__/*.{j,t}s?(x)',
'**/tests/unit/**/*.spec.{j,t}s?(x)'
],
env: {
jest: true
}
}
]
}
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -8,9 +8,22 @@ ...@@ -8,9 +8,22 @@
"lint": "vue-cli-service lint" "lint": "vue-cli-service lint"
}, },
"dependencies": { "dependencies": {
"autoprefixer": "^10.4.14",
"axios": "^1.3.4",
"core-js": "^3.8.3", "core-js": "^3.8.3",
"echarts": "^5.4.2", "echarts": "^5.4.2",
"vue": "^2.6.14" "element-ui": "^2.15.13",
"lib-flexible": "^0.3.2",
"precss": "^4.0.0",
"vue": "^2.6.14",
"vue-router": "^3.5.2",
"vue-seamless-scroll": "^1.1.23"
},
"postcss": {
"plugins": {
"autoprefixer": {},
"precss": {}
}
}, },
"devDependencies": { "devDependencies": {
"@babel/core": "^7.12.16", "@babel/core": "^7.12.16",
...@@ -20,6 +33,12 @@ ...@@ -20,6 +33,12 @@
"@vue/cli-service": "~5.0.0", "@vue/cli-service": "~5.0.0",
"eslint": "^7.32.0", "eslint": "^7.32.0",
"eslint-plugin-vue": "^8.0.3", "eslint-plugin-vue": "^8.0.3",
"less": "^4.1.3",
"less-loader": "^11.1.0",
"postcss-plugin-px2rem": "^0.8.1",
"px2rem-loader": "^0.1.9",
"style-resources-loader": "^1.5.0",
"vue-cli-plugin-style-resources-loader": "^0.1.5",
"vue-template-compiler": "^2.6.14" "vue-template-compiler": "^2.6.14"
}, },
"eslintConfig": { "eslintConfig": {
......
<!DOCTYPE html> <!DOCTYPE html>
<html lang=""> <html lang="">
<head>
<meta charset="utf-8"> <head>
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="IE=edge">
<link rel="icon" href="<%= BASE_URL %>favicon.ico"> <meta name="viewport" content="width=device-width,initial-scale=1.0">
<title><%= htmlWebpackPlugin.options.title %></title> <!-- <link rel="icon" href="<%= BASE_URL %>favicon.ico"> -->
</head> <title>
<body> 绍兴二院兰亭院区(康复医院)工程
<noscript> </title>
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong> </head>
</noscript>
<div id="app"></div> <body>
<!-- built files will be auto injected --> <noscript>
</body> <strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled.
</html> Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>
\ No newline at end of file
<template> <template>
<div id="app"> <div id="app">
<img alt="Vue logo" src="./assets/logo.png"> <router-view></router-view>
<HelloWorld msg="Welcome to Your Vue.js App"/>
</div> </div>
</template> </template>
<script> <script>
import HelloWorld from './components/HelloWorld.vue'
export default { export default {
name: 'App', name: "App",
components: { components: {},
HelloWorld };
}
}
</script> </script>
<style> <style>
* {
margin: 0;
padding: 0;
}
#app { #app {
font-family: Avenir, Helvetica, Arial, sans-serif; margin: 0px;
-webkit-font-smoothing: antialiased; background: url(assets/background.png) no-repeat;
-moz-osx-font-smoothing: grayscale; background-size: 100% 100%;
text-align: center; background-attachment: fixed;
color: #2c3e50; min-height: 100vh;
margin-top: 60px;
} }
</style> </style>
import request from "@/utils/request"
export function postAction() {
return request({
url: '',
method: 'get',
})
}
\ No newline at end of file
<template>
<div class="hello">
<h1>{{ msg }}</h1>
<p>
For a guide and recipes on how to configure / customize this project,<br>
check out the
<a href="https://cli.vuejs.org" target="_blank" rel="noopener">vue-cli documentation</a>.
</p>
<h3>Installed CLI Plugins</h3>
<ul>
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-babel" target="_blank" rel="noopener">babel</a></li>
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-eslint" target="_blank" rel="noopener">eslint</a></li>
</ul>
<h3>Essential Links</h3>
<ul>
<li><a href="https://vuejs.org" target="_blank" rel="noopener">Core Docs</a></li>
<li><a href="https://forum.vuejs.org" target="_blank" rel="noopener">Forum</a></li>
<li><a href="https://chat.vuejs.org" target="_blank" rel="noopener">Community Chat</a></li>
<li><a href="https://twitter.com/vuejs" target="_blank" rel="noopener">Twitter</a></li>
<li><a href="https://news.vuejs.org" target="_blank" rel="noopener">News</a></li>
</ul>
<h3>Ecosystem</h3>
<ul>
<li><a href="https://router.vuejs.org" target="_blank" rel="noopener">vue-router</a></li>
<li><a href="https://vuex.vuejs.org" target="_blank" rel="noopener">vuex</a></li>
<li><a href="https://github.com/vuejs/vue-devtools#vue-devtools" target="_blank" rel="noopener">vue-devtools</a></li>
<li><a href="https://vue-loader.vuejs.org" target="_blank" rel="noopener">vue-loader</a></li>
<li><a href="https://github.com/vuejs/awesome-vue" target="_blank" rel="noopener">awesome-vue</a></li>
</ul>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
props: {
msg: String
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h3 {
margin: 40px 0 0;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
a {
color: #42b983;
}
</style>
<template>
<div>
<div class="nav-header">
<div class="left-nav">
<span>XXX项目后台管理系统</span>
<router-link to="/">数字工地</router-link>
<router-link to="/realname">实名制</router-link>
<router-link to="/supervisory">视频监控</router-link>
<router-link to="/earlywarning">AI预警</router-link>
</div>
<div class="mid-title">绍兴二院兰亭院区(康复医院)工程</div>
<div class="right-nav">
<router-link to="/tower" style="margin-left: 40px"
>塔吊监测</router-link
>
<router-link to="/noise">扬尘噪音</router-link>
<div class="clock">
<div class="time">
{{ time }}
</div>
<div class="date">
<div class="week">{{ weekDay }}</div>
<div class="day">{{ date }}</div>
</div>
</div>
</div>
</div>
<div>
<router-view></router-view>
</div>
</div>
</template>
<script>
export default {
name: "Index",
data() {
return {
time: "",
weekDay: "",
date: "",
};
},
methods: {
getTime() {
let date = new Date();
let year = date.getFullYear();
let month = date.getMonth() + 1;
let day = date.getDate();
month = month > 9 ? month : "0" + month;
day = day < 10 ? "0" + day : day;
let today = year + "-" + month + "-" + day;
this.date = today;
let hour = date.getHours() < 10 ? "0" + date.getHours() : date.getHours();
let min =
date.getMinutes() < 10 ? "0" + date.getMinutes() : date.getMinutes();
let sec =
date.getSeconds() < 10 ? "0" + date.getSeconds() : date.getSeconds();
this.time = `${hour}:${min}:${sec}`;
let str = "星期";
let weekDay = new Date().getDay();
switch (weekDay) {
case 0:
str += "日";
break;
case 1:
str += "一";
break;
case 2:
str += "二";
break;
case 3:
str += "三";
break;
case 4:
str += "四";
break;
case 5:
str += "五";
break;
case 6:
str += "六";
break;
}
this.weekDay = str;
},
},
mounted() {
this.getTime();
setInterval(() => {
this.getTime();
}, 1000);
},
};
</script>
<style scoped lang="less">
.nav-header {
display: flex;
align-content: center;
line-height: 70px;
padding: 0 18px;
min-height: 78px;
height: 7.22vh;
margin: 0px;
background: url("@/assets/nav.png") no-repeat;
background-size: 100% 100%;
.left-nav {
width: calc(100% / 3);
span {
color: #fff;
margin-right: 16px;
}
}
.mid-title {
width: calc(100% / 3);
font-size: 28px;
font-family: Microsoft YaHei;
font-weight: 400;
color: #fefeff;
text-align: center;
letter-spacing: 3px;
}
.right-nav {
width: calc(100% / 3);
text-align: left;
.clock {
float: right;
width: 124px;
text-align: center;
.time {
text-align: center;
font-size: 24px;
color: #22c3ed;
letter-spacing: 4px;
line-height: 46px;
}
.date {
font-size: 12px;
color: #fff;
display: flex;
justify-content: space-between;
line-height: 14px;
}
}
}
}
a {
min-width: 66px;
text-align: center;
display: inline-block;
text-decoration: none;
margin-right: 16px;
color: #80a1c6;
padding: 9px 12px;
border: 1px solid #0f5da6;
border-radius: 4px;
line-height: 16px;
font-size: 16px;
background-image: linear-gradient(#0d3353, #183e75);
&:hover {
color: #fff;
border-color: #27acfb;
position: relative;
&::after {
position: absolute;
content: "";
width: 0;
height: 0;
bottom: 0px;
left: 50%;
transform: translateX(-50%);
border-right: solid 6px transparent;
border-left: solid 6px transparent;
border-bottom: solid 6px #22c3ed;
filter: drop-shadow(0px -1px 3px rgba(0, 234, 255, 0.8));
}
}
}
.router-link-exact-active.router-link-active {
color: #fff;
border-color: #27acfb;
position: relative;
}
.router-link-exact-active.router-link-active::after {
position: absolute;
content: "";
width: 0;
height: 0;
bottom: 0px;
left: 50%;
transform: translateX(-50%);
border-right: solid 6px transparent;
border-left: solid 6px transparent;
border-bottom: solid 6px #22c3ed;
filter: drop-shadow(0px -1px 3px rgba(0, 234, 255, 0.8));
}
</style>
\ No newline at end of file
<template>
<div class="shadow-container">
<slot />
</div>
</template>
<script>
export default {
name: "ShadowContainer",
};
</script>
<style lang="less" scoped>
.shadow-container {
position: relative;
border-radius: 10px;
padding: 20px;
border: 2px solid;
background: linear-gradient(
0deg,
rgba(4, 79, 129, 0.1) 0%,
rgba(15, 60, 89, 0.35) 28%,
#0b2950 100%
);
border-image: linear-gradient(
0deg,
rgba(255, 255, 255, 0),
rgba(7, 35, 65, 0.8),
rgba(25, 85, 117, 0.8),
rgba(15, 149, 212, 0.8)
)
2 2;
clip-path: inset(0 round 5px); //裁剪
margin-bottom: 10px;
}
.shadow-container::after {
content: "";
display: block;
position: absolute;
top: -2px;
right: -2px;
bottom: 2px;
left: -2px;
border-radius: 6px;
border-top: 2px solid;
border-color: rgba(15, 149, 212, 0.8);
pointer-events: none;
}
</style>
\ No newline at end of file
<template>
<div v-if="type == 'short'" class="title short">{{ text }}</div>
<div v-else class="title long">{{ text }}</div>
</template>
<script>
export default {
name: "Title",
props: {
type: {
type: String,
default: "short",
},
text: {
type: String,
default: "",
},
},
};
</script>
<style lang="less" scoped>
.title {
margin-bottom: 8px;
height: 50px;
line-height: 50px;
width: 100%;
text-align: center;
font-size: 20px;
font-family: Microsoft YaHei;
font-weight: bold;
color: #ffffff;
letter-spacing: 2px;
}
.short {
background: url("@/assets/title-short.png") no-repeat;
background-size: 100% 100%;
}
.long {
background: url("@/assets/title-long.png") no-repeat;
background-size: 100% 100%;
}
</style>
\ No newline at end of file
<template>
<div id="construction">
<div class="side-area">
<Title text="项目概况"></Title>
<ShadowContainer>
<div class="divider">
<div class="divider-line"></div>
<div class="divider-text">·工程名称·</div>
<div class="divider-line"></div>
</div>
<div class="construction-name">绍兴二院兰亭院区(康复医院)工程</div>
<div class="construction-details">
<div class="construction-detail">
<div class="data">288520.69</div>
<div class="text">工程造价(万元)</div>
</div>
<div class="construction-detail">
<div class="data unrecord">未录入</div>
<div class="text">建筑面积(㎡)</div>
</div>
<div class="construction-detail">
<div class="data small">
金吉祥
<br />
15567789235
</div>
<div class="text">项目经理</div>
</div>
</div>
<div class="divider">
<div class="divider-line"></div>
<div class="divider-text">·建造单位·</div>
<div class="divider-line"></div>
</div>
<div
v-for="(unit, index) in constructionUnits"
:key="index"
class="unit"
>
<div>
<div class="dot"></div>
<span class="unit-text">{{ unit.unitText }}</span>
</div>
<div>
<div class="unit-name">{{ unit.unitName }}</div>
<div class="unit-contact">{{ unit.contact }}</div>
</div>
</div>
</ShadowContainer>
<Title text="安全管理"></Title>
<ShadowContainer>
<div class="chart-container">
<img class="custom-chart" src="@/assets/chart.png" />
<div ref="securityChart" id="security-chart"></div>
</div>
</ShadowContainer>
</div>
<div class="mid-area">
<Title text="项目平面图" type="long"></Title>
<ShadowContainer>
<div class="swagger-container">
<img class="lt" src="@/assets/lt.png" alt="" />
<img class="rt" src="@/assets/rt.png" alt="" />
<img class="rb" src="@/assets/rb.png" alt="" />
<img class="lb" src="@/assets/lb.png" alt="" />
<img class="container-img" src="@/assets/swiper-pic.png" alt="" />
</div>
</ShadowContainer>
<Title text="工程进度" type="long"></Title>
<ShadowContainer>
<div class="progress-contains">
<div class="progress">
<img src="@/assets/progress.png" alt="" />
<div class="progress-container">
<div class="progress-day">
<div class="progress-count">342</div>
<div class="progress-text">总工期(天)</div>
</div>
<div class="progress-day">
<div class="progress-count" style="color: #ffaf51">288</div>
<div class="progress-text">已施工(天)</div>
</div>
</div>
</div>
<div class="steps">
<el-steps :active="active" finish-status="success">
<el-step>
<template #title>
<div class="step-title">
2022-02-19
<div class="step-status">已完成</div>
</div>
</template>
<template #description>
<div class="step-description">开工</div>
</template>
</el-step>
<el-step>
<template #title>
<div class="step-title">
2022-02-19
<div class="step-status">已完成</div>
</div>
</template>
<template #description>
<div class="step-description">工程一</div>
</template>
</el-step>
<el-step>
<template #title>
<div class="step-title">
2022-02-19
<div class="step-status">已完成</div>
</div>
</template>
<template #description>
<div class="step-description">工程二</div>
</template>
</el-step>
<el-step>
<template #title>
<div class="step-title">
2022-02-19
<div class="step-status">已完成</div>
</div>
</template>
<template #description>
<div class="step-description">工程二</div>
</template>
</el-step>
<el-step>
<template #title>
<div class="step-title">
2022-02-19
<div class="step-status">进行中</div>
</div>
</template>
<template #description>
<div class="step-description">工程二</div>
</template>
</el-step>
</el-steps>
</div>
</div>
</ShadowContainer>
</div>
<div class="side-area">
<Title text="设备情况"></Title>
<ShadowContainer>
<div class="status">
<div
class="status-count"
v-for="(status, index) in deviceStatus"
:key="index"
>
<img class="status-img" :src="status.img" alt="" />
<div class="status-detail">
<div class="status-text">
{{ status.text }}
</div>
<div class="status-number">
{{ status.counts }}
<span></span>
</div>
</div>
</div>
</div>
</ShadowContainer>
<Title text="质量问题"> </Title>
<ShadowContainer>
<div class="chart-container">
<img class="custom-chart" src="@/assets/chart.png" />
<div ref="qualityChart" id="quality-chart"></div>
</div>
</ShadowContainer>
</div>
</div>
</template>
<script>
export default {
name: "Construction",
data() {
return {
constructionUnits: [
{
unitText: "建设单位:",
unitName: "绍兴第二医院",
contact: "金吉祥(1556783245)",
},
{
unitText: "建设单位:",
unitName: "绍兴第二医院",
contact: "金吉祥(1556783245)",
},
{
unitText: "建设单位:",
unitName: "绍兴第二医院",
contact: "金吉祥(1556783245)",
},
{
unitText: "建设单位:",
unitName: "绍兴第二医院",
contact: "金吉祥(1556783245)",
},
],
pieChartData: [
{ value: 1048, name: "未整改" },
{ value: 735, name: "整改中" },
{ value: 580, name: "已完成" },
],
active: 4,
deviceStatus: [
{
img: require("@/assets/status/icon_spjk@2x.png"),
text: "视频监控",
counts: 1,
},
{
img: require("@/assets/status/icon_td@2x.png"),
text: "塔吊",
counts: 2,
},
{
img: require("@/assets/status/icon_sjt@2x.png"),
text: "升降机",
counts: 2,
},
{
img: require("@/assets/status/icon_hjgl@2x.png"),
text: "环境管理",
counts: 2,
},
{
img: require("@/assets/status/icon_ydjc@2x.png"),
text: "用电监测",
counts: 1,
},
{
img: require("@/assets/status/icon_zccl@2x.png"),
text: "在场车辆",
counts: 1,
},
{
img: require("@/assets/status/icon_sb@2x.png"),
text: "水表",
counts: 1,
},
{
img: require("@/assets/status/icon_lbfh@2x.png"),
text: "临边防护",
counts: 1,
},
{
img: require("@/assets/status/icon_xlt@2x.png"),
text: "卸料平台",
counts: 1,
},
],
};
},
methods: {
renderSecurityChart() {
const chart = this.$echarts.init(this.$refs.securityChart);
const option = {
title: {
x: "49%", //X坐标
y: "30%",
text: "0",
subtext: "安全管理",
textAlign: "center",
textStyle: {
//标题样式
fontSize: 30,
fontWeight: "bolder",
color: "rgba(255,255,255,0.7)",
},
subtextStyle: {
//副标题样式
fontSize: 16,
fontWeight: "bolder",
color: "rgba(255,255,255,0.7)",
},
},
tooltip: {
trigger: "item",
},
legend: {
itemHeight: 12,
itemWidth: 12,
icon: "rect",
bottom: "5%",
left: "center",
itemGap: 40,
textStyle: {
color: "auto",
rich: {
a: {
fontSize: 16,
verticalAlign: "top",
align: "left",
padding: [22, 0, 0, 5],
},
b: {
fontSize: 18,
align: "left",
lineHeight: 25,
padding: [0, 0, 0, 7],
},
},
},
formatter: (name) => {
let data = this.pieChartData;
let target;
for (let i = 0, l = data.length; i < l; i++) {
if (data[i].name == name) {
target = data[i].value;
}
}
let arr = [`{a|${name}}`, `{b|${target}}`];
return arr.join("\n");
},
},
series: [
{
type: "pie",
radius: ["58%", "70%"],
center: ["50%", "40%"],
avoidLabelOverlap: false,
itemStyle: {
borderRadius: 20,
borderWidth: 4,
},
label: {
show: false,
position: "center",
},
data: this.pieChartData,
},
],
};
chart.setOption(option);
},
renderQualityChart() {
const chart = this.$echarts.init(this.$refs.qualityChart);
const option = {
title: {
x: "49%", //X坐标
y: "30%",
text: "0",
subtext: "质量问题",
textAlign: "center",
textStyle: {
//标题样式
fontSize: 30,
fontWeight: "bolder",
color: "#00fcff",
},
subtextStyle: {
//副标题样式
fontSize: 16,
fontWeight: "bolder",
color: "rgba(255,255,255,0.7)",
},
},
tooltip: {
trigger: "item",
},
legend: {
itemHeight: 12,
itemWidth: 12,
icon: "rect",
bottom: "5%",
left: "center",
itemGap: 40,
textStyle: {
color: "auto",
rich: {
a: {
fontSize: 16,
verticalAlign: "top",
align: "left",
padding: [22, 0, 0, 5],
},
b: {
fontSize: 18,
align: "left",
lineHeight: 25,
padding: [0, 0, 0, 7],
},
},
},
formatter: (name) => {
let data = this.pieChartData;
let target;
for (let i = 0, l = data.length; i < l; i++) {
if (data[i].name == name) {
target = data[i].value;
}
}
let arr = [`{a|${name}}`, `{b|${target}}`];
return arr.join("\n");
},
},
series: [
{
type: "pie",
radius: ["58%", "70%"],
center: ["50%", "40%"],
avoidLabelOverlap: false,
itemStyle: {
borderRadius: 20,
borderWidth: 4,
},
label: {
show: false,
position: "center",
},
data: this.pieChartData,
},
],
};
chart.setOption(option);
},
},
mounted() {
this.renderSecurityChart();
this.renderQualityChart();
},
};
</script>
<style scoped lang="less">
#construction {
padding: 12px 20px;
display: flex;
justify-content: space-between;
}
.side-area {
width: 25%;
}
.mid-area {
width: calc(50% - 40px);
margin: 0 20px;
}
.divider {
display: flex;
justify-content: space-between;
align-items: stretch;
margin-bottom: 12px;
.divider-line {
width: calc(50% - 46px);
border-top: 1px solid #f2af58;
transform: translateY(50%);
}
.divider-text {
text-align: center;
width: 80px;
font-size: 16px;
font-weight: 400;
color: #27acfb;
}
}
.construction-name {
font-size: 20px;
font-family: Source Han Sans CN;
font-weight: 500;
font-style: italic;
color: #ffffff;
text-align: center;
margin: 20px 0;
margin-top: 0;
}
.construction-details {
display: flex;
justify-content: space-between;
text-align: center;
margin-bottom: 28px;
.construction-detail {
width: calc(100% / 3);
}
.data {
font-size: 24px;
font-weight: bold;
color: #ffaf51;
line-height: 24px;
margin-bottom: 12px;
&.unrecord {
opacity: 0.2;
}
&.small {
font-size: 12px;
line-height: 12px;
}
}
.text {
font-size: 14px;
font-weight: 400;
color: #27acfb;
}
}
.unit {
line-height: 15px;
display: flex;
justify-content: flex-start;
margin-bottom: 16px;
&:last-child {
margin-bottom: 0;
}
.dot {
width: 8px;
height: 8px;
border-radius: 50%;
background: #a3a1fb;
margin-right: 6px;
display: inline-block;
vertical-align: top;
transform: translateY(2px);
}
.unit-text {
font-size: 14px;
font-weight: 400;
color: #22c3ed;
margin-right: 14px;
}
.unit-name {
font-size: 14px;
font-weight: 400;
color: #fefefe;
margin-bottom: 4px;
}
.unit-contact {
font-size: 12px;
font-weight: 400;
color: #99a9d0;
}
}
.chart-container {
position: relative;
.custom-chart {
position: absolute;
width: 40%;
left: 50%;
transform: translateX(-50%);
top: 19%;
}
}
#security-chart,
#quality-chart {
width: 100%;
height: 400px;
}
.steps {
padding-top: 40px;
}
.step-title {
position: relative;
color: #22c3ed;
font-size: 12px;
.step-status {
position: absolute;
top: -170%;
color: #18d7b9;
font-size: 12px;
}
}
.step-description {
font-size: 14px;
color: #fff;
}
::v-deep .el-step__icon-inner {
display: none !important;
}
::v-deep .el-step__head.is-success {
::v-deep .el-step__icon {
border-width: 4px !important;
border-color: #67c23a !important;
}
}
::v-deep .el-step__icon.is-text {
border-width: 4px !important;
border-color: #22c2ec;
}
::v-deep .el-step__head.is-success {
.el-step__icon {
border-color: #67c23a !important;
}
}
.progress-contains {
padding: 8px 0;
}
.progress {
position: relative;
width: 280px;
img {
width: 100%;
}
.progress-container {
width: 100%;
position: absolute;
top: 0;
left: 0;
display: flex;
justify-content: space-between;
.progress-day {
width: 50%;
text-align: center;
padding: 12px;
}
.progress-count {
font-size: 30px;
font-weight: bold;
color: #22c2ec;
}
.progress-text {
font-size: 14px;
font-weight: 400;
color: #27acfb;
}
}
}
.swagger-container {
position: relative;
.container-img {
width: 100%;
height: 46vh;
vertical-align: top;
}
.lt,
.lb,
.rb,
.rt {
position: absolute;
width: 20px;
height: 20px;
}
.lt {
top: -2px;
left: -2px;
}
.lb {
left: -2px;
bottom: -2px;
}
.rb {
right: -2px;
bottom: -2px;
}
.rt {
right: -2px;
top: -2px;
}
}
.status {
display: flex;
justify-content: space-between;
flex-wrap: wrap;
.status-count {
width: calc(100% / 3);
padding: 20px 0px;
margin-bottom: 20px;
.status-img {
width: 64px;
height: 64px;
}
.status-detail {
display: inline-block;
vertical-align: top;
.status-text {
font-size: 14px;
font-weight: 400;
color: #ffffff;
padding-top: 12px;
}
.status-number {
font-weight: 400;
color: #25d2ff;
opacity: 0.7;
font-size: 22px;
span {
font-size: 12px;
}
}
}
}
}
</style>
\ No newline at end of file
<template>
<div>test2</div>
</template>
\ No newline at end of file
<template>
<div id="realname">
<div class="lt-area">
<div class="status">
<div
class="status-count"
v-for="(status, index) in countStatus"
:key="index"
>
<img class="status-img" :src="status.img" alt="" />
<div class="status-detail">
<div class="status-text">
{{ status.text }}
</div>
<div class="status-number">
{{ status.counts }}
</div>
</div>
</div>
</div>
</div>
<div class="mid-area">
<Title text="实时考勤"></Title>
<ShadowContainer>
<vue-seamless-scroll
:data="checkList"
:class-option="classOption"
class="warp"
@ScrollEnd="scrollEnd"
refs="scroll"
>
<div
class="person-check"
v-for="(person, index) in checkList"
:key="index"
>
<div class="portrait">
<img
class="rect"
src="@/assets/realname/portrait-rect.png"
alt=""
/>
<img class="person-head" src="@/assets/realname/portrait.png" />
</div>
<div class="person-detail">
<div class="name">
<div class="name-text">姓名:{{ person.name }}</div>
<div class="work-no">工号:{{ person.workno }}</div>
</div>
<div class="status">状态:{{ person.status }}</div>
<div class="time">时间:{{ person.time }}</div>
</div>
</div>
</vue-seamless-scroll>
</ShadowContainer>
<Title text="人员地域分布"></Title>
<ShadowContainer>
<div class="chart-container">
<img class="custom-chart" src="@/assets/chart.png" />
<div ref="areaChart" id="area-chart"></div>
</div>
</ShadowContainer>
</div>
<div class="rt-area">
<Title type="long" text="一周考勤"></Title>
<ShadowContainer>
<div class="chart-title">近一周考勤</div>
<div id="week-check-chart" ref="weekcheckChart"></div>
<div class="chart-title">近一周工种考勤</div>
<div id="week-work-chart" ref="weekworkChart"></div>
</ShadowContainer>
<div class="bottom-chart">
<div>
<Title text="近一周进出场统计"></Title>
<ShadowContainer>
<div id="in-out-chart" ref="inoutChart"></div>
</ShadowContainer>
</div>
<div>
<Title text="工种分布"></Title>
<ShadowContainer>
<div
v-for="(iType, index) in industryTypes"
:key="index"
class="i-type"
>
<div class="i-type-name">
{{ iType.text }}
</div>
<div class="slider">
<el-slider :value="50"></el-slider>
</div>
<div class="i-type-count">
<span>{{ iType.count }}</span>
</div>
</div>
</ShadowContainer>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: "Realname",
data() {
return {
countStatus: [
{
img: require("@/assets/realname/icon_b_yi@2x.png"),
text: "总人数",
counts: 1713,
},
{
img: require("@/assets/realname/icon_b_er@2x.png"),
text: "普通工人人数",
counts: 1611,
},
{
img: require("@/assets/realname/icon_b_san@2x.png"),
text: "管理人员人数",
counts: 102,
},
{
img: require("@/assets/realname/icon_b_si@2x.png"),
text: "新入场人员人数",
counts: 0,
},
{
img: require("@/assets/realname/icon_b_wu@2x.png"),
text: "今日考勤人数",
counts: 234,
},
{
img: require("@/assets/realname/icon_b_liu@2x.png"),
text: "今日在场人数",
counts: 158,
},
],
checkList: [
{
name: "简爱",
workno: "1289463894",
status: "已进场",
time: "2023年03月19日 12:23:25",
},
{
name: "简爱",
workno: "1289463894",
status: "已进场",
time: "2023年03月19日 12:23:25",
},
{
name: "简爱",
workno: "1289463894",
status: "已进场",
time: "2023年03月19日 12:23:25",
},
{
name: "简爱",
workno: "1289463894",
status: "已进场",
time: "2023年03月19日 12:23:25",
},
{
name: "简爱",
workno: "1289463894",
status: "已进场",
time: "2023年03月19日 12:23:25",
},
{
name: "简爱",
workno: "1289463894",
status: "已进场",
time: "2023年03月19日 12:23:25",
},
{
name: "简爱",
workno: "1289463894",
status: "已进场",
time: "2023年03月19日 12:23:25",
},
{
name: "简爱",
workno: "1289463894",
status: "已进场",
time: "2023年03月19日 12:23:25",
},
],
pieChartData: [
{ value: 30, name: "绍兴市" },
{ value: 10, name: "浙江省内绍兴市外" },
{ value: 1673, name: "浙江省外" },
],
industryTypes: [
{ text: "普通人员", count: 1593 },
{ text: "管理人员", count: 1593 },
{ text: "质量员", count: 1593 },
{ text: "安全员", count: 1593 },
{ text: "钢筋工", count: 1593 },
{ text: "其他工种", count: 1593 },
],
classOption: {
singleHeight: 118,
},
};
},
methods: {
renderAreaChart() {
const chart = this.$echarts.init(this.$refs.areaChart);
const option = {
title: {
x: "27%", //X坐标
y: "40%",
text: "2073",
subtext: "总人数",
textAlign: "center",
textStyle: {
//标题样式
fontSize: 30,
fontWeight: "bolder",
color: "#00fcff",
},
subtextStyle: {
//副标题样式
fontSize: 16,
fontWeight: "bolder",
color: "rgba(255,255,255,0.7)",
},
},
tooltip: {
trigger: "item",
},
legend: {
itemHeight: 12,
itemWidth: 12,
icon: "rect",
right: "0%",
top: "20%",
orient: "vertical",
itemGap: 40,
textStyle: {
color: "auto",
rich: {
a: {
fontSize: 14,
align: "left",
},
b: {
fontSize: 20,
align: "left",
lineHeight: 25,
},
},
},
formatter: (name) => {
let data = this.pieChartData;
let target;
for (let i = 0, l = data.length; i < l; i++) {
if (data[i].name == name) {
target = data[i].value;
}
}
let arr = [`{a|${name}}`, `{b|${target}} 人`];
return arr.join(" ");
},
},
series: [
{
type: "pie",
radius: ["60%", "70%"],
center: ["28%", "50%"],
avoidLabelOverlap: false,
itemStyle: {
borderRadius: 20,
borderWidth: 4,
},
label: {
show: false,
position: "center",
},
data: this.pieChartData,
},
],
};
chart.setOption(option);
},
renderWeekCheckChart() {
const chart = this.$echarts.init(this.$refs.weekcheckChart);
const option = {
color: "#00FFF0",
grid: {
top: 30,
bottom: 30,
left: 30,
right: 30,
},
xAxis: {
type: "category",
data: ["03.23", "03.24", "03.25", "03.26", "03.27", "03.28", "03.29"],
axisTick: { show: false },
axisLabel: {
textStyle: {
fontSize: "12",
color: "#c6def9",
},
},
},
yAxis: {
type: "value",
axisLabel: {
textStyle: {
fontSize: "12",
color: "#c6def9",
},
},
splitNumber: 4,
splitLine: {
lineStyle: {
color: "rgba(95, 120, 144, 0.4)",
},
},
},
series: [
{
data: [3, 4, 4, 5, 6, 7, 5],
type: "line",
symbol: "circle",
symbolSize: 12,
},
],
};
chart.setOption(option);
},
renderWeekWorkChart() {
const chart = this.$echarts.init(this.$refs.weekworkChart);
const option = {
color: ["#17FDB7", "#1abcec", "#ffaf51"],
grid: {
top: 30,
bottom: 30,
left: 30,
right: 30,
},
legend: {
orient: "horizontal",
x: "center",
y: "top",
textStyle: {
fontSize: 12,
color: "rgba(225, 239, 255, 0.7)",
},
},
xAxis: {
type: "category",
data: ["03.23", "03.24", "03.25", "03.26", "03.27", "03.28", "03.29"],
axisTick: { show: false },
axisLabel: {
textStyle: {
fontSize: "12",
color: "#c6def9",
},
},
},
yAxis: {
type: "value",
axisLabel: {
textStyle: {
fontSize: "12",
color: "#c6def9",
},
},
splitNumber: 4,
splitLine: {
lineStyle: {
color: "rgba(95, 120, 144, 0.4)",
},
},
},
series: [
{
name: "保安",
data: [2, 5, 4, 4, 7, 5, 6],
type: "line",
smooth: true,
},
{
name: "普工",
type: "line",
data: [5, 2, 3, 4, 2, 2, 4],
smooth: true,
},
{
name: "管理人员",
type: "line",
data: [0, 0, 0, 0, 0, 0, 0],
smooth: true,
},
],
};
chart.setOption(option);
},
renderInOutChart() {
const chart = this.$echarts.init(this.$refs.inoutChart);
const option = {
color: ["#FF4544", "#2980FF"],
grid: {
top: 30,
bottom: 30,
left: 30,
right: 30,
},
legend: {
orient: "horizontal",
x: "center",
y: "top",
textStyle: {
fontSize: 12,
color: "rgba(225, 239, 255, 0.7)",
},
},
xAxis: {
type: "category",
data: ["03.23", "03.24", "03.25", "03.26", "03.27", "03.28", "03.29"],
axisTick: { show: false },
axisLabel: {
textStyle: {
fontSize: "12",
color: "#c6def9",
},
},
},
yAxis: {
type: "value",
axisLabel: {
textStyle: {
fontSize: "12",
color: "#c6def9",
},
},
splitNumber: 4,
splitLine: {
lineStyle: {
color: "rgba(95, 120, 144, 0.4)",
},
},
},
series: [
{
name: "进场",
data: [2, 5, 4, 4, 7, 5, 6],
type: "line",
smooth: true,
areaStyle: {
normal: {
color: new this.$echarts.graphic.LinearGradient(0, 0, 0, 1, [
{
offset: 0,
color: "#FF4544",
},
{
offset: 1,
color: "rgba(0,0,0,0)",
},
]),
},
},
},
{
name: "离场",
type: "line",
data: [5, 2, 3, 4, 2, 2, 4],
smooth: true,
areaStyle: {
normal: {
color: new this.$echarts.graphic.LinearGradient(0, 0, 0, 1, [
{
offset: 0,
color: "#2980ff",
},
{
offset: 1,
color: "rgba(0,0,0,0)",
},
]),
},
},
},
],
};
chart.setOption(option);
},
scrollEnd: function () {
this.$refs.scroll._cancle();
setTimeout(() => {
this.$ref.scroll._startMove();
}, 3000);
},
},
mounted() {
this.renderAreaChart();
this.renderWeekCheckChart();
this.renderWeekWorkChart();
this.renderInOutChart();
},
};
</script>
<style lang="less" scoped>
#realname {
padding: 12px 20px;
display: flex;
justify-content: space-between;
.lt-area {
width: 20%;
}
.mid-area {
width: 28%;
}
.lt-area {
.status {
.status-count {
background: url("@/assets/realname/rect.png") no-repeat;
background-size: 100% 100%;
padding: 12px 20px;
margin-bottom: 20px;
.status-img {
width: 120px;
}
.status-detail {
display: inline-block;
vertical-align: top;
width: calc(100% - 120px);
.status-text {
font-size: 22px;
color: #1abcec;
text-align: right;
line-height: 60px;
}
.status-number {
text-align: right;
font-size: 44px;
font-weight: bold;
color: #c6eaf9;
line-height: 60px;
letter-spacing: 4px;
text-shadow: 0 0 5px #c6eaf9;
}
}
}
}
}
.mid-area {
margin: 0 20px;
}
.rt-area {
width: 50%;
}
}
.bottom-chart {
display: flex;
justify-content: space-between;
& > div {
width: calc(50% - 10px);
}
}
.warp {
height: 475px;
overflow: hidden;
}
.person-check {
padding: 14px;
background: rgba(20, 86, 144, 0.2);
border-radius: 4px;
margin-bottom: 12px;
display: flex;
.portrait {
position: relative;
.rect {
width: 80px;
height: 80px;
vertical-align: top;
}
.person-head {
position: absolute;
top: 8px;
width: 64px;
height: 64px;
left: 8px;
}
}
.person-detail {
font-size: 14px;
color: #c6def9;
margin-left: 24px;
width: calc(100% - 104px);
line-height: calc(80px / 3);
.name {
display: flex;
justify-content: space-between;
}
}
}
.chart-container {
position: relative;
.custom-chart {
position: absolute;
width: 30%;
top: 50%;
transform: translateY(-50%);
left: 13%;
}
}
#area-chart {
width: 100%;
height: 300px;
}
.chart-title {
background: rgba(40, 137, 195, 0.2);
border: 1px solid #217ff7;
width: 160px;
text-align: center;
font-size: 16px;
font-weight: bold;
color: #ffffff;
padding: 6px 0;
letter-spacing: 2px;
}
#week-check-chart {
width: 100%;
height: 203px;
}
#week-work-chart {
width: 100%;
height: 203px;
}
#in-out-chart {
width: 100%;
height: 300px;
}
.i-type {
display: flex;
font-size: 14px;
color: #c6def9;
padding: 4px;
.slider {
width: 70%;
vertical-align: top;
}
.i-type-name,
.i-type-count {
width: 15%;
vertical-align: top;
line-height: 42px;
text-align: right;
span {
font-size: 16px;
}
}
.i-type-name {
padding-right: 12px;
}
}
::v-deep .el-slider__bar {
background-image: linear-gradient(90deg, #152647 0%, #5a9bee 97%) !important;
height: 10px;
}
::v-deep .el-slider__runway {
background: #103153;
height: 10px;
}
::v-deep .el-slider__button {
width: 12px;
height: 12px;
}
::v-deep .el-slider__button-wrapper {
top: 50%;
transform: translateY(-50%) translateX(-50%);
}
</style>
\ No newline at end of file
<template>
<div>test4</div>
</template>
\ No newline at end of file
import Vue from 'vue' import Vue from 'vue'
import App from './App.vue' import App from './App.vue'
import router from '@/router/index'
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
import 'lib-flexible'
import Title from "@/components/Title"
import ShadowContainer from "@/components/ShadowContainer"
import * as echarts from "echarts"
import scroll from 'vue-seamless-scroll'
Vue.use(scroll)
Vue.prototype.$echarts = echarts
Vue.config.productionTip = false Vue.config.productionTip = false
Vue.use(ElementUI)
Vue.component('Title', Title)
Vue.component('ShadowContainer', ShadowContainer)
new Vue({ new Vue({
render: h => h(App), render: h => h(App),
router
}).$mount('#app') }).$mount('#app')
import Vue from 'vue'
import VueRouter from 'vue-router'
import Index from "@/components/Index"
import Construction from "@/components/construction/Index"
import RealName from "@/components/realname/Index"
import EarlyWarning from "@/components/earlywarning/Index"
import Supervisory from "@/components/supervisory/Index"
Vue.use(VueRouter)
const router = new VueRouter({
routes: [
{
path: '/', component: Index,
children: [
{ path: '', component: Construction },
{ path: 'realname', component: RealName },
{ path: 'earlywarning', component: EarlyWarning },
{ path: 'supervisory', component: Supervisory },
]
},
]
})
export default router
\ No newline at end of file
import axios from 'axios'
const request = axios.create({
withCredentials: false
})
request.interceptors.request.use(
config => {
const token = localStorage.getItem('token')
if (token) {
config.headers['X-Access-Token'] = token
}
return config
},
error => {
console.log('error', error)
return Promise.reject(new Error(error).message)
}
)
request.interceptors.response.use(
response => {
console.log('.....', response)
return response.data
},
error => {
console.log('error', error)
return Promise.reject(new Error(error).message)
}
)
export default request
const { defineConfig } = require('@vue/cli-service') const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({ module.exports = defineConfig({
transpileDependencies: true transpileDependencies: true,
productionSourceMap: false,
css: {
loaderOptions: {
postcss: {
postcssOptions: {
plugins: [
require('postcss-plugin-px2rem')({
rootValue: 55,
mediaQuery: false, //(布尔值)允许在媒体查询中转换px。
minPixelValue: 5 //设置要替换的最小像素值(3px会被转rem)。 默认 0
}),
]
}
}
}
},
publicPath: process.env.NODE_ENV == 'production' ? './' : '/',
devServer: {
port: 3000,
proxy: {
'/api': {
target: 'http://localhost:8080',
ws: false,
changeOrigin: true,
pathRewrite: {
'/api': ''
}
},
}
},
lintOnSave: true,
pluginOptions: {
"style-resources-loader": {
preProcessor: "less",
patterns: []
}
},
chainWebpack: (config) => {
config.module
.rule('css')
.test(/\.css$/)
.oneOf('vue')
.resourceQuery(/\?vue/)
.use('px2rem')
.loader('px2rem-loader')
.options({
remUnit: 75
})
}
}) })
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment