Commit 93831a15 authored by liuzhaoh's avatar liuzhaoh

Merge branch 'dev' of http://app.bmetech.com/liuzhaohui/dctomproject into dev

parents 567d99bf 24818e35
import { createWebHistory, createRouter } from 'vue-router' import { createWebHistory, createRouter } from 'vue-router'
import Dashboard from '../views/dashboard/index.vue' import Dashboard from '../views/dashboard/index.vue'
import DustOverview from '../views/dustOverview/index.vue'
import HomeView from '../views/HomeView.vue' import HomeView from '../views/HomeView.vue'
import AboutView from '../views/AboutView.vue' import AboutView from '../views/AboutView.vue'
import User from '../views/user.vue' import User from '../views/user.vue'
...@@ -19,8 +20,8 @@ const routes = [ ...@@ -19,8 +20,8 @@ const routes = [
meta: { title: '首页' }, meta: { title: '首页' },
}, },
{ {
path: '/overview', path: '/dust-overview',
component: HomeView, component: DustOverview,
meta: { title: '除尘器总览' }, meta: { title: '除尘器总览' },
}, },
{ {
......
...@@ -3,9 +3,9 @@ ...@@ -3,9 +3,9 @@
</template> </template>
<script setup> <script setup>
import { onMounted, onBeforeUnmount, ref } from 'vue'; import { onMounted, onBeforeUnmount, ref } from "vue";
import * as echarts from 'echarts'; import * as echarts from "echarts";
import { getLineOption } from '@/utils/chart'; import { getLineOption } from "@/utils/chart";
const chartRef = ref(null); const chartRef = ref(null);
let chartInstance = null; let chartInstance = null;
...@@ -13,7 +13,7 @@ let chartInstance = null; ...@@ -13,7 +13,7 @@ let chartInstance = null;
const initChart = () => { const initChart = () => {
if (chartRef.value) { if (chartRef.value) {
chartInstance = echarts.init(chartRef.value); chartInstance = echarts.init(chartRef.value);
const xData = ['01', '02', '03', '04', '05', '06', '07']; const xData = ["01", "02", "03", "04", "05", "06", "07"];
const seriesData = [120, 200, 150, 80, 60, 110, 120]; const seriesData = [120, 200, 150, 80, 60, 110, 120];
const option = getLineOption(xData, seriesData); const option = getLineOption(xData, seriesData);
chartInstance.setOption(option); chartInstance.setOption(option);
...@@ -22,7 +22,7 @@ const initChart = () => { ...@@ -22,7 +22,7 @@ const initChart = () => {
onMounted(() => { onMounted(() => {
initChart(); initChart();
window.addEventListener('resize', () => { window.addEventListener("resize", () => {
chartInstance?.resize(); chartInstance?.resize();
}); });
}); });
...@@ -38,4 +38,3 @@ onBeforeUnmount(() => { ...@@ -38,4 +38,3 @@ onBeforeUnmount(() => {
height: calc(100% - 22px); height: calc(100% - 22px);
} }
</style> </style>
\ No newline at end of file
<template>
<div class="svg-box">
<div class="svg-main">
<img src="@/assets/map.png" alt="" />
<div class="spot-box">
<div
v-for="(spot, index) in spots"
:key="index"
class="spot"
:class="[{ active: activeSpot === index }, `status-${spot.status}`]"
@mouseenter="handleSpotHover(index)"
@mouseleave="handleSpotLeave"
:style="{
left: spot.x + '%',
top: spot.y + '%',
}"
>
<div class="pulse"></div>
<!-- 连接线和详情窗 -->
<transition name="line">
<div class="connector-line" v-if="activeSpot === index"></div>
</transition>
<transition
name="detail"
@before-enter="beforeEnter"
@enter="enter"
@leave="leave"
>
<div
class="detail-window"
v-if="activeSpot === index && showDetail"
>
<div class="detail-title">{{ spot.title }}</div>
<div class="detail-content">
<div class="detail-item">
<span class="label">状态:</span>
<span class="value" :class="`text-status-${spot.status}`">{{
getStatusText(spot.status)
}}</span>
</div>
<!-- <div class="detail-item">
<span class="label">数值:</span>
<span class="value">{{ spot.value }}</span>
</div> -->
<div class="detail-item">
<span class="label">描述:</span>
<span class="value">{{ spot.description }}</span>
</div>
</div>
</div>
</transition>
</div>
</div>
</div>
</div>
</template>
<script setup>
import { onMounted, onBeforeUnmount, ref } from "vue";
import * as echarts from "echarts";
import { getLineOption } from "@/utils/chart";
// 定义坐标点位数据
const spots = ref([
{
x: 41,
y: 22,
title: "4#除尘器",
value: "89%",
status: "normal",
description: "无异常",
},
{
x: 45,
y: 70,
title: "站点B",
value: "92%",
status: "normal",
description: "运行正常",
},
{
x: 65,
y: 36,
title: "3#除尘器",
value: "78%",
status: "warning",
description: "三仓室存在轻微泄漏",
},
{
x: 60,
y: 70,
title: "2#除尘器",
value: "45%",
status: "error",
description: "除尘器脉冲阀故障或者提升阀故障",
},
]);
const activeSpot = ref(null);
const showDetail = ref(false);
const hoverTimer = ref(null);
const clearTimer = () => {
if (hoverTimer.value) {
clearTimeout(hoverTimer.value);
hoverTimer.value = null;
}
};
const handleSpotHover = (index) => {
clearTimer();
activeSpot.value = index;
hoverTimer.value = setTimeout(() => {
showDetail.value = true;
hoverTimer.value = null;
}, 300);
};
const handleSpotLeave = () => {
clearTimer();
showDetail.value = false;
hoverTimer.value = setTimeout(() => {
activeSpot.value = null;
hoverTimer.value = null;
}, 300);
};
// 详情窗动画钩子
const beforeEnter = (el) => {
el.style.opacity = 0;
el.style.transform = "translateX(-20px)";
};
const enter = (el, done) => {
el.style.transition = "all 0.3s ease-out";
setTimeout(() => {
el.style.opacity = 1;
el.style.transform = "translateX(0)";
}, 0);
};
const leave = (el) => {
el.style.transition = "all 0.3s ease-in";
el.style.opacity = 0;
el.style.transform = "translateX(-20px)";
};
const getStatusText = (status) => {
const statusMap = {
normal: "正常",
warning: "警告",
error: "异常",
};
return statusMap[status] || status;
};
onMounted(() => {});
onBeforeUnmount(() => {
clearTimer();
});
</script>
<style scoped lang="scss">
.svg-box {
position: relative;
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
.svg-main {
position: relative;
display: inline-block;
height: 100%;
}
img {
display: block;
width: auto;
height: 100%;
}
}
.spot-box {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
pointer-events: none;
}
.spot {
position: absolute;
width: 15px;
height: 15px;
background: rgb(253, 48, 2);
border-radius: 50%;
transform: translate(-50%, -50%);
pointer-events: auto;
cursor: pointer;
z-index: 2;
// 状态颜色
&.status-normal {
background: #08c733;
.pulse {
background: #08c733;
}
&.active .pulse {
background: #08c733;
}
}
&.status-warning {
background: #f5c701;
.pulse {
background: #f5c701;
}
&.active .pulse {
background: #f5c701;
}
}
&.status-error {
background: #ff6a6a;
.pulse {
background: #ff6a6a;
}
&.active .pulse {
background: #ff6a6a;
}
}
&.active {
box-shadow: 0 0 10px rgba(255, 255, 255, 0.5);
}
.pulse {
position: absolute;
width: 100%;
height: 100%;
background: rgb(253, 48, 2);
border-radius: 50%;
animation: pulse 1.5s ease-out infinite;
}
.connector-line {
position: absolute;
top: 50%;
left: 50%;
width: 60px; // 缩短连接线长度
height: 2px;
background: linear-gradient(90deg, currentColor, rgba(89, 93, 89, 0.4));
transform-origin: left center;
transform: rotate(-45deg);
z-index: -1;
}
// 连接线动画
.line-enter-active {
transition: all 0.3s ease-out;
transform-origin: left center;
}
.line-leave-active {
transition: all 0.3s ease-in;
transform-origin: left center;
}
.line-enter-from,
.line-leave-to {
opacity: 0;
width: 0;
}
.detail-window {
position: absolute;
left: calc(100% + 35px); // 减小与连接线的距离
top: -40px; // 调整垂直位置
width: 200px;
background: rgba(0, 22, 40, 0.5);
backdrop-filter: blur(8px);
border: 1px solid rgba(255, 255, 255, 0.3);
border-radius: 8px;
padding: 12px;
color: #fff;
pointer-events: none;
z-index: 3;
.text-status-normal {
color: #00ff9d !important;
}
.text-status-warning {
color: #ffa500 !important;
}
.text-status-error {
color: #ff3b3b !important;
}
&::before {
content: "";
position: absolute;
left: -6px;
top: 50%;
transform: translateY(-50%);
width: 0;
height: 0;
border-top: 6px solid transparent;
border-bottom: 6px solid transparent;
border-right: 6px solid rgba(255, 255, 255, 0.3);
}
.detail-title {
font-size: 16px;
font-weight: bold;
color: #fff;
// color: #00ff9d;
margin-bottom: 8px;
}
.detail-content {
font-size: 14px;
.detail-item {
display: flex;
margin-bottom: 4px;
.label {
width: 50px;
color: rgba(255, 255, 255, 0.7);
}
.value {
width: calc(100% - 55px);
color: #fff;
}
}
}
}
}
@keyframes pulse {
0% {
transform: scale(1);
opacity: 1;
}
100% {
transform: scale(3);
opacity: 0;
}
}
</style>
<template> <template>
<div class="message-list" @mouseenter="pauseScroll" @mouseleave="resumeScroll"> <div
<div class="message-wrapper" ref="messageWrapper"> class="message-list"
<div @mouseenter="pauseScroll"
class="message-item" @mouseleave="resumeScroll"
v-for="(message, index) in extendedList" >
:key="index" <div class="message-wrapper" ref="messageWrapper">
> <div
<span class="time">{{ message.time }}</span> class="message-item"
<div class="content"><span class="title">{{ message.title }}</span>{{ message.content }}</div> v-for="(message, index) in extendedList"
:key="index"
>
<span class="time">{{ message.time }}</span>
<div class="content">
<span class="title">{{ message.title }}</span
>{{ message.content }}
</div> </div>
</div> </div>
</div> </div>
</template> </div>
</template>
<script setup>
import { ref, onMounted, onBeforeUnmount, nextTick, watch } from 'vue'; <script setup>
import { ref, onMounted, onBeforeUnmount, nextTick, watch } from "vue";
const props = defineProps({
msgList: { const props = defineProps({
type: Array, msgList: {
default: () => [] type: Array,
} default: () => [],
}); },
});
const extendedList = ref([]);
const messageWrapper = ref(null); const extendedList = ref([]);
const itemHeight = 34; // 一条消息高度 const messageWrapper = ref(null);
const scrollInterval = 3000; // 每 2 秒滚动一次 const itemHeight = 34; // 一条消息高度
let timer = null; const scrollInterval = 3000; // 每 2 秒滚动一次
let isPaused = false; let timer = null;
let isPaused = false;
// 滚动逻辑:每 2 秒滚动一条(50px)
const startScroll = () => { // 滚动逻辑:每 2 秒滚动一条(50px)
stopScroll(); const startScroll = () => {
const wrapper = messageWrapper.value; stopScroll();
if (!wrapper) return; const wrapper = messageWrapper.value;
if (!wrapper) return;
timer = setInterval(() => {
if (isPaused) return; timer = setInterval(() => {
if (isPaused) return;
const currentTop = parseInt(wrapper.style.transform.replace('translateY(', '').replace('px)', '')) || 0;
const nextTop = currentTop - itemHeight; const currentTop =
parseInt(
wrapper.style.transition = 'transform 0.5s'; wrapper.style.transform.replace("translateY(", "").replace("px)", "")
wrapper.style.transform = `translateY(${nextTop}px)`; ) || 0;
const nextTop = currentTop - itemHeight;
const listHeight = (extendedList.value.length / 2) * itemHeight;
if (Math.abs(nextTop) >= listHeight) { wrapper.style.transition = "transform 0.5s";
// 到底了,重置 wrapper.style.transform = `translateY(${nextTop}px)`;
setTimeout(() => {
wrapper.style.transition = 'none'; const listHeight = (extendedList.value.length / 2) * itemHeight;
wrapper.style.transform = 'translateY(0)'; if (Math.abs(nextTop) >= listHeight) {
}, 500); // 等待动画完成后重置 // 到底了,重置
} setTimeout(() => {
}, scrollInterval); wrapper.style.transition = "none";
}; wrapper.style.transform = "translateY(0)";
}, 500); // 等待动画完成后重置
const stopScroll = () => {
if (timer) {
clearInterval(timer);
timer = null;
}
};
const pauseScroll = () => {
isPaused = true;
};
const resumeScroll = () => {
isPaused = false;
};
// 数据更新时刷新滚动状态
const updateScroll = () => {
stopScroll();
if (props.msgList.length < 5) {
extendedList.value = [...props.msgList];
nextTick(() => {
if (messageWrapper.value) {
messageWrapper.value.style.transform = 'translateY(0)';
messageWrapper.value.style.transition = 'none';
}
});
} else {
extendedList.value = [...props.msgList, ...props.msgList]; // 实现无缝滚动
nextTick(() => {
if (messageWrapper.value) {
messageWrapper.value.style.transform = 'translateY(0)';
messageWrapper.value.style.transition = 'none';
}
startScroll();
});
} }
}; }, scrollInterval);
};
// 生命周期钩子
onMounted(() => {
updateScroll();
});
onBeforeUnmount(() => {
stopScroll();
});
watch(() => props.msgList, () => {
updateScroll();
}, { deep: true });
</script>
<style scoped>
.message-list {
position: relative;
overflow: hidden;
max-height: 160px; /* 7条 * 50px */
width: 100%;
height: calc(100% - 22px);
}
.message-wrapper {
width: 100%;
}
.message-item {
display: flex;
align-items: center;
font-size: 14px;
height: 32px;
line-height: 32px;
padding: 1px 0;
max-width: 100%;
const stopScroll = () => {
if (timer) {
clearInterval(timer);
timer = null;
} }
.message-item .time { };
color: #58616b;
margin-right: 5px; const pauseScroll = () => {
min-width: 80px; isPaused = true;
flex-shrink: 0; };
} const resumeScroll = () => {
.message-item .title { isPaused = false;
margin-right: 5px; };
color: #0c0b0b;
font-weight: bold; // 数据更新时刷新滚动状态
} const updateScroll = () => {
.message-item .content { stopScroll();
flex: 1; if (props.msgList.length < 5) {
color: #58616b; extendedList.value = [...props.msgList];
overflow: hidden; nextTick(() => {
text-overflow:ellipsis; if (messageWrapper.value) {
white-space: nowrap; messageWrapper.value.style.transform = "translateY(0)";
messageWrapper.value.style.transition = "none";
}
});
} else {
extendedList.value = [...props.msgList, ...props.msgList]; // 实现无缝滚动
nextTick(() => {
if (messageWrapper.value) {
messageWrapper.value.style.transform = "translateY(0)";
messageWrapper.value.style.transition = "none";
}
startScroll();
});
} }
</style> };
\ No newline at end of file // 生命周期钩子
onMounted(() => {
updateScroll();
});
onBeforeUnmount(() => {
stopScroll();
});
watch(
() => props.msgList,
() => {
updateScroll();
},
{ deep: true }
);
</script>
<style scoped>
.message-list {
position: relative;
overflow: hidden;
max-height: 170px; /* 7条 * 50px */
width: 100%;
height: calc(100% - 22px);
}
.message-wrapper {
width: 100%;
}
.message-item {
display: flex;
align-items: center;
font-size: 14px;
height: 32px;
line-height: 32px;
padding: 1px 0;
max-width: 100%;
cursor: pointer;
}
.message-item:hover {
background: #f0f0f0;
}
.message-item .time {
color: #58616b;
margin-right: 5px;
min-width: 80px;
flex-shrink: 0;
}
.message-item .title {
margin-right: 5px;
color: #0c0b0b;
font-weight: bold;
}
.message-item .content {
flex: 1;
color: #58616b;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
</style>
...@@ -28,8 +28,7 @@ ...@@ -28,8 +28,7 @@
</div> </div>
<div class="map-box"> <div class="map-box">
<img src="@/assets/map.png" alt="" /> <map-svg></map-svg>
<div class="spot-box"></div>
</div> </div>
</div> </div>
</template> </template>
...@@ -39,6 +38,7 @@ import { ref, onMounted, onBeforeUnmount, computed, nextTick } from "vue"; ...@@ -39,6 +38,7 @@ import { ref, onMounted, onBeforeUnmount, computed, nextTick } from "vue";
import { useRoute, useRouter } from "vue-router"; import { useRoute, useRouter } from "vue-router";
import msgItem from "./components/msg-item.vue"; import msgItem from "./components/msg-item.vue";
import chartLine from "./components/chart-line.vue"; import chartLine from "./components/chart-line.vue";
import mapSvg from "./components/map-svg.vue";
const percentageO = ref(20); const percentageO = ref(20);
const percentageT = ref(62); const percentageT = ref(62);
...@@ -61,8 +61,7 @@ const msgList = ref([ ...@@ -61,8 +61,7 @@ const msgList = ref([
}, },
{ {
title: "2#除尘器", title: "2#除尘器",
content: content: "除尘器脉冲阀故障或者提升阀故障",
"除尘器脉冲阀故障或者提升阀故障",
time: "05-18 08:00", time: "05-18 08:00",
}, },
{ {
...@@ -133,6 +132,7 @@ onBeforeUnmount(() => {}); ...@@ -133,6 +132,7 @@ onBeforeUnmount(() => {});
align-items: center; align-items: center;
justify-content: space-between; justify-content: space-between;
height: 15rem; height: 15rem;
& > div { & > div {
background: #ffffff; background: #ffffff;
border-radius: 6px; border-radius: 6px;
...@@ -140,6 +140,7 @@ onBeforeUnmount(() => {}); ...@@ -140,6 +140,7 @@ onBeforeUnmount(() => {});
padding: 16px; padding: 16px;
box-sizing: border-box; box-sizing: border-box;
} }
.title { .title {
font-size: 18px; font-size: 18px;
font-weight: normal; font-weight: normal;
...@@ -147,6 +148,7 @@ onBeforeUnmount(() => {}); ...@@ -147,6 +148,7 @@ onBeforeUnmount(() => {});
line-height: 22px; line-height: 22px;
margin-bottom: 10px; margin-bottom: 10px;
} }
.msg-box { .msg-box {
width: calc(38% - 16px); width: calc(38% - 16px);
height: 100%; height: 100%;
...@@ -155,6 +157,7 @@ onBeforeUnmount(() => {}); ...@@ -155,6 +157,7 @@ onBeforeUnmount(() => {});
.indicators-box { .indicators-box {
width: 24%; width: 24%;
height: 100%; height: 100%;
.indicators-num { .indicators-num {
font-size: 37px; font-size: 37px;
font-weight: bold; font-weight: bold;
...@@ -162,6 +165,7 @@ onBeforeUnmount(() => {}); ...@@ -162,6 +165,7 @@ onBeforeUnmount(() => {});
line-height: 44px; line-height: 44px;
margin-bottom: 10px; margin-bottom: 10px;
} }
.indicators-item { .indicators-item {
height: 22px; height: 22px;
font-size: 15px; font-size: 15px;
...@@ -170,6 +174,7 @@ onBeforeUnmount(() => {}); ...@@ -170,6 +174,7 @@ onBeforeUnmount(() => {});
line-height: 22px; line-height: 22px;
} }
} }
.line-box { .line-box {
width: calc(38% - 16px); width: calc(38% - 16px);
height: 100%; height: 100%;
...@@ -186,14 +191,6 @@ onBeforeUnmount(() => {}); ...@@ -186,14 +191,6 @@ onBeforeUnmount(() => {});
box-shadow: 0px 3px 6px 0px rgba(13, 15, 18, 0.1); box-shadow: 0px 3px 6px 0px rgba(13, 15, 18, 0.1);
padding: 16px; padding: 16px;
box-sizing: border-box; box-sizing: border-box;
display: flex;
align-items: center;
justify-content: center;
img {
display: block;
width: auto;
height: 100%;
}
} }
} }
</style> </style>
<template>
<div class="page-container dust-container">
<div class="header">
<div class="item-box">
<img src="@/assets/icons/warn.png" alt="dust" />
<div class="title">
<span>泄漏告警(条)</span>
<div class="content">6</div>
</div>
</div>
<div class="item-box">
<img src="@/assets/icons/health.png" alt="dust" />
<div class="title">
<span>综合健康度</span>
<div class="content">98%</div>
</div>
</div>
<div class="item-box">
<img src="@/assets/icons/close.png" alt="dust" />
<div class="title">
<span>闭环(条)</span>
<div class="content">6</div>
</div>
</div>
</div>
<div class="content-box">
<div class="search">
<el-form :inline="true" :model="formInline" class="demo-form-inline">
<el-form-item label="工序">
<el-select
v-model="formInline.region"
placeholder="请选择工序"
style="width: 120px"
clearable
>
<el-option
v-for="item in options"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
<el-form-item label="除尘器名称">
<el-input
v-model="formInline.deviceName"
placeholder="请输入除尘器名称"
style="width: 200px"
clearable
/>
</el-form-item>
<el-form-item>
<el-button type="default" class="default-btn" @click="onSubmit"
>重置</el-button
>
<el-button type="primary" class="search-btn" @click="onSubmit"
>查询</el-button
>
<el-button type="success" class="add-btn" @click="onSubmit"
>新增</el-button
>
</el-form-item>
</el-form>
</div>
<el-table :data="tableData" style="width: 100%">
<el-table-column
v-for="item in tableColumns"
:key="item.prop"
:prop="item.prop"
:label="item.label"
/>
</el-table>
</div>
</div>
</template>
<script setup>
import { ref, onMounted, onBeforeUnmount, computed, nextTick } from "vue";
const formInline = ref({
deviceName: "",
region: 1,
});
const options = ref([
{
value: "1",
label: "转炉",
},
{
value: "2",
label: "炼铁",
},
]);
const tableColumns = ref([
{
prop: "date",
label: "Date",
},
{
prop: "name",
label: "Name",
},
]);
const tableData = [
{
date: "2016-05-03",
name: "Tom",
state: "California",
city: "Los Angeles",
address: "No. 189, Grove St, Los Angeles",
zip: "CA 90036",
},
{
date: "2016-05-02",
name: "Tom",
state: "California",
city: "Los Angeles",
address: "No. 189, Grove St, Los Angeles",
zip: "CA 90036",
},
{
date: "2016-05-04",
name: "Tom",
state: "California",
city: "Los Angeles",
address: "No. 189, Grove St, Los Angeles",
zip: "CA 90036",
},
{
date: "2016-05-01",
name: "Tom",
state: "California",
city: "Los Angeles",
address: "No. 189, Grove St, Los Angeles",
zip: "CA 90036",
},
{
date: "2016-05-08",
name: "Tom",
state: "California",
city: "Los Angeles",
address: "No. 189, Grove St, Los Angeles",
zip: "CA 90036",
},
{
date: "2016-05-06",
name: "Tom",
state: "California",
city: "Los Angeles",
address: "No. 189, Grove St, Los Angeles",
zip: "CA 90036",
},
{
date: "2016-05-07",
name: "Tom",
state: "California",
city: "Los Angeles",
address: "No. 189, Grove St, Los Angeles",
zip: "CA 90036",
},
];
const onSubmit = () => {
console.log("submit!", formInline.value);
};
onMounted(async () => {});
onBeforeUnmount(() => {});
</script>
<style lang="scss" scoped>
.dust-container {
width: 100%;
height: calc(100% - 14px);
box-sizing: border-box;
.header {
display: flex;
// justify-content: space-between;
align-items: center;
gap: 16px;
.item-box {
flex: 1;
max-width: 420px;
height: 130px;
background-color: #fff;
border: 1.5px solid #e8e8e8;
border-radius: 6px;
box-shadow: 0px 1.33px 16px 0px rgba(83, 100, 170, 0.1);
padding: 16px;
box-sizing: border-box;
display: flex;
align-items: center;
img {
width: 72px;
height: 72px;
margin-right: 20px;
}
.title {
width: 100%;
span {
color: rgba(36, 48, 71, 0.75);
line-height: 22px;
font-size: 14px;
font-weight: 500;
}
}
.content {
color: #273849;
line-height: 30px;
font-size: 42px;
font-weight: 600;
margin-top: 10px;
}
}
}
.content-box {
margin-top: 24px;
.search {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 16px;
}
}
.default-btn {
width: 85px;
}
.search-btn {
width: 85px;
background: #2182a0;
border: 1px solid #2182a0;
}
.add-btn {
width: 85px;
}
}
</style>
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