Merge remote-tracking branch 'origin/dev' into dev

dev
wangpeng 2024-04-11 16:12:24 +08:00
commit d51784a22d
12 changed files with 149 additions and 567 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 850 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 455 KiB

View File

@ -1,6 +1,6 @@
<template>
<div class="tc mt-20 mb-20">
<img :src="src" alt="" width="200" height="200" />
<div :class="['tc', margin ? 'mt-20 mb-20' : '']">
<img :src="src" alt="" :width="width" :height="height" />
</div>
</template>
@ -16,10 +16,22 @@ const props = defineProps({
required: true,
default: "",
},
width: {
type: Number,
default: 200,
},
height: {
type: Number,
default: 200,
},
margin: {
type: Boolean,
default: true,
},
});
const src = useQRCode(() => props.src, {
width: 200,
height: 200,
width: props.width,
height: props.height,
margin: 1,
correctLevel: "H",
});

View File

@ -1,104 +0,0 @@
<template>
<el-tabs v-model="active">
<el-tab-pane label="平台公告" name="first" lazy>
<seamless-scroll
:list="platformAnnouncementList"
hover
class="scroll"
:step="0.5"
:single-wait-time="1000"
:single-height="24"
:model-value="!data.viewDialog.visible && active === 'first'"
>
<div
v-for="(item, index) in platformAnnouncementList"
:key="index"
class="line-1 item"
@click="fnPlatformAnnouncementView(item.NOTICE_ID)"
>
{{ item.SYNOPSIS }}
</div>
</seamless-scroll>
</el-tab-pane>
<el-tab-pane label="企业公告" name="second" lazy>
<seamless-scroll
:list="corporateAnnouncementList"
hover
class="scroll"
:step="0.5"
:single-wait-time="1000"
:single-height="24"
:model-value="!data.viewDialog.visible && active === 'second'"
>
<div
v-for="(item, index) in corporateAnnouncementList"
:key="index"
class="line-1 item"
@click="fnCorporateAnnouncementView(item.NOTICECORP_ID)"
>
{{ item.SYNOPSIS }}
</div>
</seamless-scroll>
</el-tab-pane>
</el-tabs>
<announcement-view
v-model:visible="data.viewDialog.visible"
:info="data.viewDialog.info"
/>
</template>
<script setup>
import { reactive, ref } from "vue";
import {
getCorporateAnnouncement,
getCorporateAnnouncementView,
getPlatformAnnouncement,
getPlatformAnnouncementView,
} from "@/request/index.js";
import useListData from "@/assets/js/useListData.js";
import AnnouncementView from "./announcement_view.vue";
import { Vue3SeamlessScroll as SeamlessScroll } from "vue3-seamless-scroll";
const active = ref("first");
const { list: platformAnnouncementList } = useListData(
getPlatformAnnouncement,
{ otherParams: { STATUS: 1 } }
);
const { list: corporateAnnouncementList } = useListData(
getCorporateAnnouncement,
{ otherParams: { STATUS: 1 } }
);
const data = reactive({
viewDialog: {
visible: false,
info: {},
},
});
const fnPlatformAnnouncementView = async (NOTICE_ID) => {
const resData = await getPlatformAnnouncementView({ NOTICE_ID });
data.viewDialog.visible = true;
data.viewDialog.info = resData.pd;
};
const fnCorporateAnnouncementView = async (NOTICECORP_ID) => {
const resData = await getCorporateAnnouncementView({ NOTICECORP_ID });
data.viewDialog.visible = true;
data.viewDialog.info = resData.pd;
};
</script>
<style scoped lang="scss">
.scroll {
height: 120px;
overflow: hidden;
.item {
padding: 4px 0;
font-size: 14px;
cursor: pointer;
&:hover {
color: #409eff;
}
}
}
</style>

View File

@ -1,159 +0,0 @@
<template>
<div>
<el-calendar v-model="value" class="mlr--18 border content">
<template #date-cell="{ data: { day } }">
<p class="calendar-data" @click="fnView(day)">
<span v-for="(item, index) in dayTime" :key="index">
<span v-if="day === item" class="budge" />
</span>
{{ day.split("-").slice(2).join() }}
</p>
</template>
</el-calendar>
<div class="mlr--18 border p-10 content">
<div class="title">本日工作提醒</div>
<div style="height: 42px">
<div v-if="wjcNum > 0" class="text-red mb-10">
需进行 {{ wjcNum }} 项隐患排查
</div>
<div class="text-green">已进行 {{ yjcNum }} 项隐患排查</div>
</div>
</div>
<div class="mlr--18 border p-10 content">
<div class="title">{{ currentDate }}日程安排</div>
<ul>
<li v-for="(item, index) in scheduleList" :key="index" class="line-1">
{{ item.desc }}
</li>
<li v-if="scheduleList.length === 0"></li>
</ul>
</div>
<schedule-add
v-model:visible="data.addOrEditDialog.visible"
v-model:form="data.addOrEditDialog.form"
:title="data.addOrEditDialog.title"
:type="data.addOrEditDialog.type"
@get-data="fnGetSchedule(data.addOrEditDialog.form.noteDate)"
/>
</div>
</template>
<script setup>
import { nextTick, reactive, ref } from "vue";
import { getCalendar, getWorkReminder } from "@/request/index.js";
import dayjs from "dayjs";
import ScheduleAdd from "./schedule_add.vue";
const value = ref(new Date());
const dayTime = ref([]);
const wjcNum = ref(0);
const yjcNum = ref(0);
const currentDate = ref(dayjs().format("YYYY-MM-DD"));
const scheduleList = ref([]);
const data = reactive({
addOrEditDialog: {
visible: false,
type: "",
title: "",
form: {
SCHEDULE_ID: "",
biaoti: "",
neirong: "",
noteDate: "",
},
},
});
const fnGetCalendar = async () => {
const resData = await getCalendar();
for (let i = 0; i < resData.varList.length; i++) {
dayTime.value.push(resData.varList[i].date);
}
};
const fnGetWorkReminder = async () => {
const resData = await getWorkReminder();
wjcNum.value = resData.wjcNum;
yjcNum.value = resData.yjcNum;
};
const fnGetSchedule = async (CDATA, type = "") => {
const resData = await getCalendar({ CDATA });
if (type) {
data.addOrEditDialog.visible = true;
await nextTick();
data.addOrEditDialog.title = CDATA + "号日程";
if (resData.varList.length > 0) {
data.addOrEditDialog.type = "edit";
data.addOrEditDialog.form.SCHEDULE_ID = resData.varList[0].id;
data.addOrEditDialog.form.biaoti = resData.varList[0].title;
data.addOrEditDialog.form.neirong = resData.varList[0].desc;
data.addOrEditDialog.form.noteDate = resData.varList[0].date;
} else {
data.addOrEditDialog.form.SCHEDULE_ID = Math.random();
data.addOrEditDialog.form.noteDate = CDATA;
data.addOrEditDialog.type = "add";
}
} else scheduleList.value = resData.varList;
};
fnGetCalendar();
fnGetWorkReminder();
fnGetSchedule(currentDate.value);
const fnView = (date) => {
currentDate.value = date;
if (dayjs().diff(dayjs(date), "day") > 0) {
fnGetSchedule(date);
} else {
fnGetSchedule(date, "add");
fnGetSchedule(date);
}
};
</script>
<style scoped lang="scss">
.calendar-data {
position: relative;
.budge {
width: 6px;
height: 6px;
background-color: #ff4d4f;
border-radius: 50%;
position: absolute;
top: 5px;
right: 5px;
}
}
.title {
font-weight: bold;
padding-bottom: 10px;
}
.border {
border-top: 1px solid #102b60;
}
.content {
font-size: 14px;
}
ul {
height: 106px;
overflow: hidden;
li {
padding: 4px 0;
}
}
:deep {
.el-calendar-table .el-calendar-day {
height: 40px;
line-height: 40px;
padding: 0;
text-align: center;
}
.el-calendar__body {
padding: 10px;
}
}
</style>

View File

@ -1,133 +0,0 @@
<template>
<el-card>
<div class="searchForm">
<el-date-picker
v-model="dates"
type="daterange"
range-separator="至"
start-placeholder="开始日期"
end-placeholder="结束日期"
value-format="YYYY-MM-DD"
format="YYYY-MM-DD"
style="width: 80% !important"
/>
<el-button type="primary" class="ml-10" @click="fnGetData">
搜索
</el-button>
</div>
<div id="main3" />
</el-card>
</template>
<script setup>
import { onBeforeUnmount, onMounted, ref } from "vue";
import * as echarts from "echarts";
import { getChecklistCheck } from "@/request/index.js";
import dayjs from "dayjs";
let myChart3;
const dates = ref([
dayjs().startOf("year").format("YYYY-MM-DD"),
dayjs().endOf("year").format("YYYY-MM-DD"),
]);
const fnGetData = async () => {
const resData = await getChecklistCheck({
STARTTIME: dates.value[0],
ENDTIME: dates.value[1],
});
myChart3 && myChart3.dispose();
fnInitEcharts(resData.varList);
};
const fnInitEcharts = (data) => {
myChart3 = echarts.init(document.querySelector("#main3"));
const x_Data = [];
const y_Data = [];
for (let i = 0; i < data.length; i++) {
x_Data.push(data[i].percentage);
y_Data.push(data[i].name);
}
const option = {
title: {
text: "清单检查完成率统计(单位%",
top: "3%",
textStyle: {
fontSize: "14",
color: "#fff",
fontWeight: "700",
},
},
tooltip: {
trigger: "axis",
axisPointer: {
type: "shadow",
},
},
grid: {
left: "3%",
right: "4%",
bottom: "3%",
top: "15%",
containLabel: true,
},
xAxis: {
show: false,
type: "value",
boundaryGap: [0, 0.01],
},
yAxis: {
type: "category",
data: y_Data,
axisLabel: {
color: "#fff",
},
},
series: [
{
type: "bar",
data: x_Data,
label: {
show: true,
position: "right",
color: "#fff",
},
barWidth: 15,
itemStyle: {
color: function (params) {
const colorList = [
"#ee6666",
"#73c0de",
"#3ca272",
"#fc8452",
"#9a60b4",
"#5470c6",
];
return colorList[params.dataIndex];
},
},
},
],
};
myChart3.setOption(option);
};
onMounted(() => {
fnGetData();
window.onresize = function () {
myChart3 && myChart3.resize();
};
});
onBeforeUnmount(() => {
myChart3 = null;
});
</script>
<style scoped lang="scss">
#main3 {
width: 100%;
height: 305px;
}
.searchForm {
position: absolute;
right: 10px;
z-index: 1;
}
</style>

View File

@ -3,7 +3,7 @@
<div class="wrap">
<div class="flex top">
<div class="img">
<img src="@/assets/images/public/loginbg.jpg" alt="" />
<img src="/src/assets/images/public/bg.jpg" alt="" />
</div>
<div class="info">
<div>

View File

@ -1,118 +0,0 @@
<template>
<el-card>
<div id="main2" />
</el-card>
</template>
<script setup>
import { onBeforeUnmount, onMounted } from "vue";
import * as echarts from "echarts";
import { getRiskManagement } from "@/request/large_screen_data_display.js";
let myChart2;
const fnGetData = async () => {
const { riskAll } = await getRiskManagement();
fnInitEcharts(riskAll);
};
const fnInitEcharts = (data) => {
myChart2 = echarts.init(document.querySelector("#main2"));
let acount = 0;
let bcount = 0;
let ccount = 0;
let dcount = 0;
for (let i = 0; data.length > i; i++) {
if (data[i].LEVELID) {
if (data[i].LEVELID === "levelA") acount = data[i].COUNT;
if (data[i].LEVELID === "levelB") bcount = data[i].COUNT;
if (data[i].LEVELID === "levelC") ccount = data[i].COUNT;
if (data[i].LEVELID === "levelD") dcount = data[i].COUNT;
}
}
const option = {
title: {
text: "风险分级统计",
textStyle: {
fontSize: "14",
color: "#fff",
fontWeight: "700",
},
},
color: ["#10b9f8", "#ffc600", "#f49545", "#ec2c26"],
tooltip: {
trigger: "item",
},
grid: {},
legend: {
orient: "vertical",
left: "6%",
top: "20%",
textStyle: {
color: "#fff",
},
},
series: [
{
name: "风险类型",
type: "pie",
radius: ["30%", "70%"],
center: ["64%", "49%"],
avoidLabelOverlap: false,
itemStyle: {
borderColor: "rgb(8, 24, 58)",
borderWidth: 2,
},
label: {
show: false,
position: "center",
},
emphasis: {
label: {
show: true,
fontSize: "18",
fontWeight: "bold",
color: "#fff",
},
},
labelLine: {
show: false,
},
data: [
{
value: dcount,
name: "低风险",
},
{
value: ccount,
name: "一般风险",
},
{
value: bcount,
name: "较大风险",
},
{
value: acount,
name: "重大风险",
},
],
},
],
};
myChart2.setOption(option);
};
onMounted(() => {
fnGetData();
window.onresize = function () {
myChart2 && myChart2.resize();
};
});
onBeforeUnmount(() => {
myChart2 = null;
});
</script>
<style scoped lang="scss">
#main2 {
width: 100%;
height: 305px;
}
</style>

View File

@ -41,11 +41,6 @@ import doublePrevention from "./components/doublePrevention.vue";
import info from "./components/info.vue";
import statistics from "./components/statistics.vue";
import waybill from "./components/waybill.vue";
// import RiskClassification from "./components/risk_classification.vue";
// import ChecklistCheck from "./components/checklist_check.vue";
// import Announcement from "./components/announcement.vue";
// import Calendar from "./components/calendar.vue";
</script>
<style lang="scss" scoped>

View File

@ -1,8 +1,23 @@
<template>
<div class="login">
<div class="main">
<div class="title">交通运输安全生产综合管理系统</div>
<div class="midbg">
<div class="logo">
<img src="/src/assets/images/login/logo.png" alt="" />
</div>
<div class="title">
<div class="chinese">交通运输企业智慧安全管理平台</div>
<div class="english">
INTELLIGENT SAFETY MANAGEMENT PLATFORM FOR TRANSPORTATION
ENTERPRISES
</div>
</div>
</div>
<div class="form">
<div class="title">
欢迎登录系统
<div class="line" />
</div>
<el-form
ref="formRef"
:model="data.form"
@ -16,7 +31,7 @@
tabindex="1"
>
<template #prepend>
<icon-people theme="filled" size="16" fill="#909399" />
<icon-people size="16" fill="#9ba2a8" />
</template>
</el-input>
</el-form-item>
@ -28,12 +43,7 @@
tabindex="2"
>
<template #prepend>
<icon-lock
theme="filled"
size="16"
fill="#909399"
:stroke-width="3"
/>
<icon-lock size="16" fill="#9ba2a8" :stroke-width="3" />
</template>
</el-input>
</el-form-item>
@ -44,6 +54,24 @@
<el-button native-type="submit">登录</el-button>
</el-form-item>
</el-form>
<el-popover
placement="bottom"
title="扫码下载APP"
:width="150"
trigger="click"
>
<div>
<layout-qr-code
src="111111"
:width="120"
:height="120"
:margin="false"
/>
</div>
<template #reference>
<div class="tip">企业安全APP</div>
</template>
</el-popover>
</div>
</div>
</div>
@ -58,6 +86,7 @@ import { useUserStore } from "@/pinia/user";
import { Login } from "@/request/api";
import { debounce } from "throttle-debounce";
import useFormValidate from "@/assets/js/useFormValidate.js";
import LayoutQrCode from "@/components/qr_code/index.vue";
const router = useRouter();
const formRef = ref(null);
@ -119,60 +148,106 @@ const fnSubmitLogin = async () => {
margin: 0 auto;
height: 100vh;
position: relative;
background: url("../../assets/images/public/loginbg.jpg") no-repeat top center;
background: url("/src/assets/images/login/loginbg.png") no-repeat top center;
background-size: 100% 100%;
.main {
width: 600px;
padding-top: 280px;
margin: 0 auto;
width: 90%;
height: 90%;
background: url("/src/assets/images/login/midbg.png") no-repeat top center;
background-size: 100% 100%;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
box-shadow: 0 0 10px rgba(0, 0, 0, 0.5);
.midbg {
width: calc(100% - 540px);
height: 100%;
position: relative;
.logo {
img {
width: 206px;
height: 50px;
margin-top: 35px;
margin-left: 35px;
}
}
.title {
width: 100%;
text-align: center;
font-size: 36px;
color: #ffffff;
width: max-content;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
.chinese {
font-size: 48px;
font-weight: bold;
color: #fff;
}
.english {
margin-top: 15px;
font-size: 16px;
color: #fff;
}
}
}
.form {
width: 478px;
min-height: 290px;
padding: 20px 40px;
border-radius: 5px;
background: rgba(8, 22, 59, 0.36);
border: 1px solid rgba(31, 58, 136, 0.9);
margin: 60px auto 0;
box-shadow: 0 0 20px rgba(47, 85, 124, 0.2) inset;
width: 540px;
height: 100%;
background-color: #fff;
position: absolute;
right: 0;
top: 0;
padding: 250px 80px 0 80px;
.title {
color: #666;
text-align: center;
font-weight: 700;
font-size: 18px;
margin-bottom: 20px;
}
color: #444;
font-weight: bold;
font-size: 22px;
display: flex;
align-items: center;
flex-direction: column;
margin-bottom: 50px;
.el-form-item {
width: 325px;
margin: 20px auto;
.line {
margin-top: 10px;
background-color: #2490fb;
height: 5px;
width: 80px;
border-radius: 5px;
}
}
.el-input {
height: 40px;
}
--el-input-bg-color: #f2f4f9;
--el-input-text-color: #000;
--el-fill-color-light: #f2f4f9;
--el-input-border-color: #dde0eb;
}
.button {
.el-button {
background: #0948d5;
border: 1px solid #276aff;
height: 45px;
width: 100%;
color: #ffffff;
margin-top: 10px;
height: 50px;
font-size: 16px;
background-color: #265feb;
border-color: #265feb;
}
}
}
.tip {
width: max-content;
cursor: pointer;
position: absolute;
right: 80px;
}
}
}
@ -181,4 +256,18 @@ const fnSubmitLogin = async () => {
padding-top: 5px !important;
}
}
:global(.el-popover.el-popper) {
--el-popover-bg-color: #fff;
--el-popover-border-color: #fff;
--el-fill-color-blank: #fff;
--el-border-color: #fff;
--el-text-color-regular: #000;
--el-popover-title-text-color: #000;
--el-popover-title-font-size: 12px;
}
:global(.el-popover__title) {
text-align: center;
}
</style>