feat: 可视化大屏
@ -1,30 +1,40 @@
|
|||||||
const Layout = () => import("@/layout/index.vue");
|
const Layout = () => import('@/layout/index.vue');
|
||||||
|
|
||||||
export default [
|
export default [
|
||||||
{
|
{
|
||||||
path: "/login",
|
path: '/login',
|
||||||
name: "Login",
|
name: 'Login',
|
||||||
component: () => import("@/views/login/index.vue"),
|
component: () => import('@/views/login/index.vue'),
|
||||||
meta: {
|
meta: {
|
||||||
title: "登录",
|
title: '登录',
|
||||||
showLink: false,
|
showLink: false,
|
||||||
rank: 101
|
rank: 101,
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/redirect",
|
path: '/redirect',
|
||||||
component: Layout,
|
component: Layout,
|
||||||
meta: {
|
meta: {
|
||||||
title: "加载中...",
|
title: '加载中...',
|
||||||
showLink: false,
|
showLink: false,
|
||||||
rank: 102
|
rank: 102,
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: '/redirect/:path(.*)',
|
||||||
|
name: 'Redirect',
|
||||||
|
component: () => import('@/layout/redirect.vue'),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/screen',
|
||||||
|
name: 'Screen',
|
||||||
|
component: () => import('@/views/screen/index.vue'),
|
||||||
|
meta: {
|
||||||
|
title: '可视化大屏',
|
||||||
|
showLink: false,
|
||||||
|
rank: 103,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
children: [
|
|
||||||
{
|
|
||||||
path: "/redirect/:path(.*)",
|
|
||||||
name: "Redirect",
|
|
||||||
component: () => import("@/layout/redirect.vue")
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
] satisfies Array<RouteConfigsTable>;
|
] satisfies Array<RouteConfigsTable>;
|
||||||
|
|||||||
@ -0,0 +1,3 @@
|
|||||||
|
import CountUp from "./count-up.vue"
|
||||||
|
export default CountUp
|
||||||
|
|
||||||
@ -0,0 +1,90 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { computed, ref ,onBeforeUpdate, nextTick} from "vue";
|
||||||
|
import { merge } from "lodash-es";
|
||||||
|
import { useElementSize } from "@vueuse/core";
|
||||||
|
import type { PropType } from "vue";
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
color: {
|
||||||
|
type: Array as unknown as PropType<[string, string]>,
|
||||||
|
default: () => [],
|
||||||
|
},
|
||||||
|
backgroundColor: {
|
||||||
|
type: String,
|
||||||
|
default: "transparent",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const defaultColor = ["#6586ec", "#2cf7fe"];
|
||||||
|
const domRef = ref(null);
|
||||||
|
const { width, height } = useElementSize(domRef,{width:0,height:0}, { box: 'border-box' });
|
||||||
|
const mergedColor = computed<[string, string]>(() => {
|
||||||
|
return merge(defaultColor, props.color);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="dv-border-box-13 dv-border-box" ref="domRef">
|
||||||
|
<svg :width="width" :height="height" class="dv-border-svg-container">
|
||||||
|
<path
|
||||||
|
:fill="backgroundColor"
|
||||||
|
:stroke="mergedColor[0]"
|
||||||
|
:d="`
|
||||||
|
M 5 20 L 5 10 L 12 3 L 60 3 L 68 10
|
||||||
|
L ${width - 20} 10 L ${width - 5} 25
|
||||||
|
L ${width - 5} ${height - 5} L 20 ${height - 5}
|
||||||
|
L 5 ${height - 20} L 5 20
|
||||||
|
`"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<path
|
||||||
|
fill="transparent"
|
||||||
|
stroke-width="3"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-dasharray="10, 5"
|
||||||
|
:stroke="mergedColor[0]"
|
||||||
|
:d="`M 16 9 L 61 9`"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<path
|
||||||
|
fill="transparent"
|
||||||
|
stroke="{mergedColor[1]}"
|
||||||
|
:d="`M 5 20 L 5 10 L 12 3 L 60 3 L 68 10`"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<path
|
||||||
|
fill="transparent"
|
||||||
|
:stroke="mergedColor[1]"
|
||||||
|
:d="`M ${width - 5} ${height - 30} L ${width - 5} ${height - 5} L ${
|
||||||
|
width - 30
|
||||||
|
} ${height - 5}`"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
<div class="dv-border-box-content">
|
||||||
|
<slot></slot>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.dv-border-box {
|
||||||
|
position: relative;
|
||||||
|
box-sizing: border-box;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
.dv-border-svg-container {
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
top: 0px;
|
||||||
|
left: 0px;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
.dv-border-box-content {
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
import BorderBox13 from "./border-box-13.vue"
|
||||||
|
|
||||||
|
export default BorderBox13
|
||||||
@ -0,0 +1,186 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { onMounted, reactive, ref, watch } from "vue";
|
||||||
|
import type { DefaultConfigType } from "./index.d";
|
||||||
|
import { cloneDeep } from "lodash-es";
|
||||||
|
import { merge } from "lodash-es";
|
||||||
|
const mergedConfig = ref<any>(null);
|
||||||
|
const capsuleLength = ref<any>([]);
|
||||||
|
const capsuleValue = ref<any>([]);
|
||||||
|
const labelData = ref<any>([]);
|
||||||
|
// const labelDataLength = ref<any>([]);
|
||||||
|
|
||||||
|
const defaultConfig = reactive<DefaultConfigType>({
|
||||||
|
// Colors (hex|rgb|rgba|color keywords) ['#000', 'rgb(0, 0, 0)', 'rgba(0, 0, 0, 1)', 'red']
|
||||||
|
colors: [
|
||||||
|
"#37a2da",
|
||||||
|
"#32c5e9",
|
||||||
|
"#67e0e3",
|
||||||
|
"#9fe6b8",
|
||||||
|
"#ffdb5c",
|
||||||
|
"#ff9f7f",
|
||||||
|
"#fb7293",
|
||||||
|
],
|
||||||
|
unit: "",
|
||||||
|
showValue: false, // Show item value
|
||||||
|
});
|
||||||
|
const props = withDefaults(
|
||||||
|
defineProps<{
|
||||||
|
config: object | any;
|
||||||
|
data: Array<{
|
||||||
|
name: string;
|
||||||
|
value: string | number;
|
||||||
|
}>;
|
||||||
|
}>(),
|
||||||
|
{
|
||||||
|
config: () => { },
|
||||||
|
data: () => [],
|
||||||
|
}
|
||||||
|
);
|
||||||
|
const calcData = () => {
|
||||||
|
mergeConfig();
|
||||||
|
calcCapsuleLengthAndLabelData();
|
||||||
|
};
|
||||||
|
const mergeConfig = () => {
|
||||||
|
mergedConfig.value = merge(cloneDeep(defaultConfig), props.config || {});
|
||||||
|
};
|
||||||
|
const calcCapsuleLengthAndLabelData = () => {
|
||||||
|
if (!props.data.length) return;
|
||||||
|
const newcapsuleValue = props.data.map((item: any) => item.value);
|
||||||
|
const maxValue = Math.max(...newcapsuleValue);
|
||||||
|
capsuleValue.value = newcapsuleValue;
|
||||||
|
capsuleLength.value = newcapsuleValue.map((v: any) =>
|
||||||
|
maxValue ? v / maxValue : 0
|
||||||
|
);
|
||||||
|
const oneFifth = maxValue / 5;
|
||||||
|
const newlabelData = Array.from(
|
||||||
|
new Set(new Array(6).fill(0).map((v, i) => Math.ceil(i * oneFifth)))
|
||||||
|
);
|
||||||
|
labelData.value = newlabelData;
|
||||||
|
// labelDataLength.value = Array.from(newlabelData).map((v) =>
|
||||||
|
// maxValue ? v / maxValue : 0
|
||||||
|
// );
|
||||||
|
// console.log(labelDataLength.value);
|
||||||
|
};
|
||||||
|
watch(
|
||||||
|
() => props.data,
|
||||||
|
(newval: any) => {
|
||||||
|
calcData();
|
||||||
|
},
|
||||||
|
);
|
||||||
|
watch(
|
||||||
|
() => props.config,
|
||||||
|
(newval: any) => {
|
||||||
|
calcData();
|
||||||
|
},
|
||||||
|
);
|
||||||
|
onMounted(() => {
|
||||||
|
calcData();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="dv-capsule-chart">
|
||||||
|
<template v-if="mergedConfig">
|
||||||
|
<div class="label-column">
|
||||||
|
<div v-for="item in data" :key="item.name">
|
||||||
|
{{ item.name }}
|
||||||
|
</div>
|
||||||
|
<div> </div>
|
||||||
|
</div>
|
||||||
|
<div class="capsule-container">
|
||||||
|
<div class="capsule-item" v-for="(capsule, index) in capsuleLength" :key="index">
|
||||||
|
<div class="capsule-item-column" :style="`width: ${capsule * 100}%; background-color: ${mergedConfig.colors[index % mergedConfig.colors.length]
|
||||||
|
};`">
|
||||||
|
<div v-if="mergedConfig.showValue" class="capsule-item-value">
|
||||||
|
{{ capsuleValue[index] }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="unit-label">
|
||||||
|
<div v-for="(label, index) in labelData" :key="label + index">
|
||||||
|
{{ label }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="unit-text" v-if="mergedConfig.unit">
|
||||||
|
{{ mergedConfig.unit }}
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.dv-capsule-chart {
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
box-sizing: border-box;
|
||||||
|
padding: 10px;
|
||||||
|
color: #fff;
|
||||||
|
|
||||||
|
.label-column {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: space-between;
|
||||||
|
box-sizing: border-box;
|
||||||
|
padding-right: 10px;
|
||||||
|
text-align: right;
|
||||||
|
font-size: 12px;
|
||||||
|
|
||||||
|
div {
|
||||||
|
height: 20px;
|
||||||
|
line-height: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.capsule-container {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
.capsule-item {
|
||||||
|
box-shadow: 0 0 3px #999;
|
||||||
|
height: 10px;
|
||||||
|
margin: 5px 0px;
|
||||||
|
border-radius: 5px;
|
||||||
|
|
||||||
|
.capsule-item-column {
|
||||||
|
position: relative;
|
||||||
|
height: 8px;
|
||||||
|
margin-top: 1px;
|
||||||
|
border-radius: 5px;
|
||||||
|
transition: all 0.3s;
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.capsule-item-value {
|
||||||
|
font-size: 12px;
|
||||||
|
transform: translateX(100%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.unit-label {
|
||||||
|
height: 20px;
|
||||||
|
font-size: 12px;
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.unit-text {
|
||||||
|
text-align: right;
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-end;
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 20px;
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -0,0 +1,6 @@
|
|||||||
|
export interface DefaultConfigType {
|
||||||
|
|
||||||
|
colors: Array<String>;
|
||||||
|
unit:string,
|
||||||
|
showValue:Boolean
|
||||||
|
}
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
import CapsuleChart from "./capsule-chart.vue"
|
||||||
|
export * from "./index.d"
|
||||||
|
export default CapsuleChart
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
import ItemWrap from "./item-wrap.vue"
|
||||||
|
export default ItemWrap
|
||||||
@ -0,0 +1,77 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import BorderBox13 from '../datav/border-box-13';
|
||||||
|
const props = withDefaults(
|
||||||
|
defineProps<{
|
||||||
|
// 标题
|
||||||
|
title: number | string;
|
||||||
|
}>(),
|
||||||
|
{
|
||||||
|
title: '',
|
||||||
|
}
|
||||||
|
);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<BorderBox13>
|
||||||
|
<div
|
||||||
|
class="item_title"
|
||||||
|
v-if="title !== ''"
|
||||||
|
>
|
||||||
|
<div class="zuo"></div>
|
||||||
|
<span class="title-inner"> {{ title }} </span>
|
||||||
|
<div class="you"></div>
|
||||||
|
</div>
|
||||||
|
<div :class="title !== '' ? 'item_title_content' : 'item_title_content_def'">
|
||||||
|
<slot></slot></div
|
||||||
|
></BorderBox13>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
$item-title-height: 38px;
|
||||||
|
$item_title_content-height: calc(100% - 38px);
|
||||||
|
|
||||||
|
.item_title {
|
||||||
|
height: $item-title-height;
|
||||||
|
line-height: $item-title-height;
|
||||||
|
width: 100%;
|
||||||
|
color: #31abe3;
|
||||||
|
text-align: center;
|
||||||
|
// background: linear-gradient(to right, transparent, #0f0756, transparent);
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
.zuo,
|
||||||
|
.you {
|
||||||
|
width: 58px;
|
||||||
|
height: 14px;
|
||||||
|
background-image: url('@/assets/img/titles/zuo.png');
|
||||||
|
}
|
||||||
|
|
||||||
|
.you {
|
||||||
|
transform: rotate(180deg);
|
||||||
|
}
|
||||||
|
.title-inner {
|
||||||
|
font-weight: 900;
|
||||||
|
letter-spacing: 2px;
|
||||||
|
background: linear-gradient(92deg, #0072ff 0%, #00eaff 48.8525390625%, #01aaff 100%);
|
||||||
|
-webkit-background-clip: text;
|
||||||
|
-webkit-text-fill-color: transparent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.dv-border-box-content) {
|
||||||
|
box-sizing: border-box;
|
||||||
|
padding: 6px 16px 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item_title_content {
|
||||||
|
height: $item_title_content-height;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item_title_content_def {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
import ScaleScreen from './scale-screen.vue'
|
||||||
|
|
||||||
|
export default ScaleScreen
|
||||||
@ -1,5 +1,5 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, defineComponent, onBeforeMount, onMounted, ref, watch, nextTick } from 'vue';
|
import { computed, onBeforeMount, onMounted, ref, watch, nextTick } from 'vue';
|
||||||
import type { CSSProperties } from 'vue';
|
import type { CSSProperties } from 'vue';
|
||||||
import { throttle } from 'lodash-es';
|
import { throttle } from 'lodash-es';
|
||||||
type propsType = {
|
type propsType = {
|
||||||
@ -0,0 +1,193 @@
|
|||||||
|
<template>
|
||||||
|
<div class="d-flex jc-center title_wrap">
|
||||||
|
<div class="zuojuxing"></div>
|
||||||
|
<div class="youjuxing"></div>
|
||||||
|
<div class="guang"></div>
|
||||||
|
<div class="d-flex jc-center">
|
||||||
|
<div class="title">
|
||||||
|
<span class="title-text">{{ currentOrg.name }}可视化大屏</span>
|
||||||
|
<IconifyIconOffline
|
||||||
|
:style="{ transform: `rotate(${ratation}deg)` }"
|
||||||
|
class="select-icon"
|
||||||
|
width="30px"
|
||||||
|
height="30px"
|
||||||
|
:icon="CaretRight"
|
||||||
|
@click="toggleShowSelectOrg"
|
||||||
|
/>
|
||||||
|
<ul :class="['select-ul', { fade: isShow }]">
|
||||||
|
<li
|
||||||
|
v-for="item in orgList"
|
||||||
|
:key="item.id"
|
||||||
|
:class="{ selected: item.id === currentOrg.id }"
|
||||||
|
@click="toggleSelectOrg(item)"
|
||||||
|
>
|
||||||
|
{{ item.name }}
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="timers">
|
||||||
|
<span> {{ dateData.dateYear }} {{ dateData.dateWeek }} {{ dateData.dateDay }}</span>
|
||||||
|
<LaySidebarFullScreen id="full-screen" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="jsx">
|
||||||
|
import { ref, reactive, inject, computed } from 'vue';
|
||||||
|
import dayjs from 'dayjs';
|
||||||
|
import LaySidebarFullScreen from '@/layout/components/lay-sidebar/components/SidebarFullScreen.vue';
|
||||||
|
import CaretRight from '@iconify-icons/ep/caret-right';
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
orgList: {
|
||||||
|
type: Array,
|
||||||
|
default: () => [],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const currentOrg = inject('currentOrg');
|
||||||
|
const emits = defineEmits(['changeOrg']);
|
||||||
|
const isShow = ref(false);
|
||||||
|
const toggleShowSelectOrg = () => {
|
||||||
|
isShow.value = !isShow.value;
|
||||||
|
};
|
||||||
|
const toggleSelectOrg = (item) => {
|
||||||
|
isShow.value = false;
|
||||||
|
emits('changeOrg', item);
|
||||||
|
};
|
||||||
|
const ratation = computed(() => (isShow.value ? 90 : 0));
|
||||||
|
|
||||||
|
const weekday = ['周日', '周一', '周二', '周三', '周四', '周五', '周六'];
|
||||||
|
const dateData = reactive({
|
||||||
|
dateDay: '',
|
||||||
|
dateYear: '',
|
||||||
|
dateWeek: '',
|
||||||
|
timing: null,
|
||||||
|
});
|
||||||
|
const timeFn = () => {
|
||||||
|
dateData.timing = setInterval(() => {
|
||||||
|
dateData.dateDay = dayjs().format('YYYY-MM-DD HH:mm:ss');
|
||||||
|
dateData.dateWeek = weekday[dayjs().day()];
|
||||||
|
}, 1000);
|
||||||
|
};
|
||||||
|
timeFn();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.title_wrap {
|
||||||
|
height: 60px;
|
||||||
|
background-image: url('../img/headers/top.png');
|
||||||
|
background-size: cover;
|
||||||
|
background-position: center center;
|
||||||
|
position: relative;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
|
||||||
|
.guang {
|
||||||
|
position: absolute;
|
||||||
|
bottom: -26px;
|
||||||
|
background-image: url('../img/headers/guang.png');
|
||||||
|
background-position: 80px center;
|
||||||
|
width: 100%;
|
||||||
|
height: 56px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.zuojuxing,
|
||||||
|
.youjuxing {
|
||||||
|
position: absolute;
|
||||||
|
top: -2px;
|
||||||
|
width: 140px;
|
||||||
|
height: 6px;
|
||||||
|
background-image: url('../img/headers/juxing1.png');
|
||||||
|
}
|
||||||
|
|
||||||
|
.zuojuxing {
|
||||||
|
left: 11%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.youjuxing {
|
||||||
|
right: 11%;
|
||||||
|
transform: rotate(180deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.timers {
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
top: 30px;
|
||||||
|
font-size: 18px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
color: #fff;
|
||||||
|
|
||||||
|
& > span:first-child {
|
||||||
|
line-height: 1;
|
||||||
|
padding-right: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fullscreen-icon {
|
||||||
|
cursor: pointer;
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.title {
|
||||||
|
position: relative;
|
||||||
|
// width: 500px;
|
||||||
|
text-align: center;
|
||||||
|
background-size: cover;
|
||||||
|
color: transparent;
|
||||||
|
height: 60px;
|
||||||
|
line-height: 46px;
|
||||||
|
|
||||||
|
.title-text {
|
||||||
|
font-size: 38px;
|
||||||
|
font-weight: 900;
|
||||||
|
letter-spacing: 6px;
|
||||||
|
width: 100%;
|
||||||
|
background: linear-gradient(92deg, #0072ff 0%, #00eaff 48.8525390625%, #01aaff 100%);
|
||||||
|
-webkit-background-clip: text;
|
||||||
|
-webkit-text-fill-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.select-icon {
|
||||||
|
cursor: pointer;
|
||||||
|
display: inline-block;
|
||||||
|
color: #0072ff;
|
||||||
|
vertical-align: text-bottom;
|
||||||
|
transition: transform 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.select-ul {
|
||||||
|
max-height: 0;
|
||||||
|
opacity: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
position: absolute;
|
||||||
|
color: #f1f1f1;
|
||||||
|
background: rgb(48, 49, 51);
|
||||||
|
border-radius: 10px;
|
||||||
|
width: 150px;
|
||||||
|
z-index: 999;
|
||||||
|
left: 50%;
|
||||||
|
margin-left: 150px;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
padding: 5px 0;
|
||||||
|
|
||||||
|
li {
|
||||||
|
cursor: pointer;
|
||||||
|
height: 40px;
|
||||||
|
line-height: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
li:hover {
|
||||||
|
background: rgb(104, 104, 105);
|
||||||
|
}
|
||||||
|
li.selected {
|
||||||
|
background: rgb(104, 104, 105);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.select-ul.fade {
|
||||||
|
max-height: 500px;
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
After Width: | Height: | Size: 47 KiB |
|
After Width: | Height: | Size: 62 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 9.3 KiB |
|
After Width: | Height: | Size: 289 KiB |
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 1.5 KiB |
@ -0,0 +1,61 @@
|
|||||||
|
<template>
|
||||||
|
<scale-screen
|
||||||
|
width="1920"
|
||||||
|
height="1080"
|
||||||
|
:delay="300"
|
||||||
|
:full-screen="false"
|
||||||
|
:box-style="{
|
||||||
|
background: '#03050c',
|
||||||
|
overflow: 'hidden',
|
||||||
|
}"
|
||||||
|
:wrapper-style="{}"
|
||||||
|
>
|
||||||
|
<div class="content_wrap">
|
||||||
|
<Headers
|
||||||
|
:orgList="orgList"
|
||||||
|
@changeOrg="changeOrg"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</scale-screen>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="jsx">
|
||||||
|
import { ref, provide } from 'vue';
|
||||||
|
import ScaleScreen from './components/common/scale-screen';
|
||||||
|
import Headers from './components/header.vue';
|
||||||
|
|
||||||
|
const orgList = ref([
|
||||||
|
{
|
||||||
|
id: 'all',
|
||||||
|
name: '全局',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'org1',
|
||||||
|
name: '机构一',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'org2',
|
||||||
|
name: '机构二',
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
const currentOrg = ref({
|
||||||
|
id: 'all',
|
||||||
|
name: '全局',
|
||||||
|
});
|
||||||
|
provide('currentOrg', currentOrg);
|
||||||
|
const changeOrg = (item) => {
|
||||||
|
currentOrg.value = item;
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.content_wrap {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
padding: 16px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
background-image: url('./img/pageBg.png');
|
||||||
|
background-size: cover;
|
||||||
|
background-position: center center;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -0,0 +1,19 @@
|
|||||||
|
<template>
|
||||||
|
<iframe
|
||||||
|
ref="iframe"
|
||||||
|
:src="src"
|
||||||
|
frameborder="0"
|
||||||
|
width="100%"
|
||||||
|
height="100%"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="jsx">
|
||||||
|
import { ref } from 'vue';
|
||||||
|
defineOptions({
|
||||||
|
name: 'TemplateScreen',
|
||||||
|
});
|
||||||
|
|
||||||
|
const origin = window.location.origin;
|
||||||
|
const src = ref(`${origin}/#/screen`);
|
||||||
|
</script>
|
||||||