From 796f1fce7951ca1dd4ba5785f25d86bf5ca9dcd5 Mon Sep 17 00:00:00 2001
From: 刘嘉威 <daidaibg@163.com>
Date: 星期四, 27 十月 2022 17:23:27 +0800
Subject: [PATCH] feat:增加无缝轮播组件 增加左下 右下组件
---
src/views/setting.vue | 45 ++
types/global.d.ts | 2
src/components/seamless-scroll/index.ts | 2
src/views/index/left-bottom.vue | 228 ++++++++++++
components.d.ts | 2
src/api/modules/index.ts | 4
src/views/index/right-bottom.vue | 193 ++++++++++
src/views/index/index.vue | 3
src/components/seamless-scroll/seamless-scroll.vue | 407 ++++++++++++++++++++++
src/assets/css/variable.scss | 1
src/components/empty-com/index.ts | 2
src/components/empty-com/empty-com.vue | 9
src/mock/mock-index.ts | 81 +++
src/stores/setting/setting.ts | 53 ++
src/assets/css/main.scss | 44 ++
15 files changed, 1,038 insertions(+), 38 deletions(-)
diff --git a/components.d.ts b/components.d.ts
index fba7b29..00bed56 100644
--- a/components.d.ts
+++ b/components.d.ts
@@ -12,10 +12,12 @@
ElDrawer: typeof import('element-plus/es')['ElDrawer']
ElRadio: typeof import('element-plus/es')['ElRadio']
ElRadioGroup: typeof import('element-plus/es')['ElRadioGroup']
+ EmptyCom: typeof import('./src/components/empty-com/empty-com.vue')['default']
ItemWrap: typeof import('./src/components/item-wrap/item-wrap.vue')['default']
MessageContent: typeof import('./src/components/Plugins/MessageContent/index.vue')['default']
RouterLink: typeof import('vue-router')['RouterLink']
RouterView: typeof import('vue-router')['RouterView']
ScaleScreen: typeof import('./src/components/scale-screen/scale-screen.vue')['default']
+ SeamlessScroll: typeof import('./src/components/seamless-scroll/seamless-scroll.vue')['default']
}
}
diff --git a/src/api/modules/index.ts b/src/api/modules/index.ts
index 7cff390..e0e896c 100644
--- a/src/api/modules/index.ts
+++ b/src/api/modules/index.ts
@@ -4,8 +4,8 @@
"centerMap":"/bigscreen/centerMap",
"centerBottom":"/bigscreen/installationPlan",
- // 'big3':"/bigscreen/sbtx", //璁惧鎻愰啋
+ 'leftBottom':"/bigscreen/leftBottom", //鍧愪笅
'rightTop':"/bigscreen/alarmNum", //鎶ヨ娆℃暟
- // 'big5':'/bigscreen/ssyj',//瀹炴椂棰勮
+ 'rightBottom':'/bigscreen/rightBottom',//鍙充笅
'rightCenter':'/bigscreen/ranking',// 鎶ヨ鎺掑悕
}
\ No newline at end of file
diff --git a/src/assets/css/main.scss b/src/assets/css/main.scss
index fbc751c..08381e3 100644
--- a/src/assets/css/main.scss
+++ b/src/assets/css/main.scss
@@ -51,4 +51,48 @@
.el-message__content {
color: var(--yh-text-color-primary);
}
+ }
+
+ .beautify-scroll-def {
+ overflow-y: auto;
+
+ &::-webkit-scrollbar-thumb {
+ //婊氬姩鏉$殑璁剧疆
+ background-color: rgba(14, 59, 150, 0);
+ background-clip: padding-box;
+ border-radius: 4px;
+ }
+
+ &:hover {
+ &::-webkit-scrollbar-thumb {
+ //婊氬姩鏉$殑璁剧疆
+ background-color: rgba(14, 59, 150, 0.5);
+ background-clip: padding-box;
+ border-radius: 4px;
+ }
+ }
+
+ &::-webkit-scrollbar-track-piece {
+ //婊氬姩鏉″嚬妲界殑棰滆壊锛岃繕鍙互璁剧疆杈规灞炴��
+ background-color: transparent;
+ }
+
+ &::-webkit-scrollbar {
+ //婊氬姩鏉$殑瀹藉害
+ width: 8px;
+ height: 8px;
+ }
+
+
+
+ &::-webkit-scrollbar-thumb:hover {
+ background-color: rgba(14, 59, 150, .8);
+ }
+ }
+
+ .text-content {
+ width: 100%;
+ display: flex;
+ min-height: calc(100% - 60px);
+ justify-content: space-between;
}
\ No newline at end of file
diff --git a/src/assets/css/variable.scss b/src/assets/css/variable.scss
index e69de29..0dec46e 100644
--- a/src/assets/css/variable.scss
+++ b/src/assets/css/variable.scss
@@ -0,0 +1 @@
+$primary-color: #1890ff;
\ No newline at end of file
diff --git a/src/components/empty-com/empty-com.vue b/src/components/empty-com/empty-com.vue
new file mode 100644
index 0000000..b87eb83
--- /dev/null
+++ b/src/components/empty-com/empty-com.vue
@@ -0,0 +1,9 @@
+<script setup lang="ts"></script>
+
+<template>
+ <div>
+ <slot></slot>
+ </div>
+</template>
+
+<style scoped lang="scss"></style>
diff --git a/src/components/empty-com/index.ts b/src/components/empty-com/index.ts
new file mode 100644
index 0000000..2cf8d9f
--- /dev/null
+++ b/src/components/empty-com/index.ts
@@ -0,0 +1,2 @@
+import EmptyCom from "./empty-com.vue"
+export default EmptyCom
\ No newline at end of file
diff --git a/src/components/seamless-scroll/index.ts b/src/components/seamless-scroll/index.ts
new file mode 100644
index 0000000..a422cf6
--- /dev/null
+++ b/src/components/seamless-scroll/index.ts
@@ -0,0 +1,2 @@
+import SeamlessScroll from "./seamless-scroll.vue"
+export default SeamlessScroll
\ No newline at end of file
diff --git a/src/components/seamless-scroll/seamless-scroll.vue b/src/components/seamless-scroll/seamless-scroll.vue
new file mode 100644
index 0000000..cf42f6a
--- /dev/null
+++ b/src/components/seamless-scroll/seamless-scroll.vue
@@ -0,0 +1,407 @@
+<script setup lang="ts">
+import {
+ computed,
+ defineComponent,
+ onBeforeMount,
+ onMounted,
+ ref,
+ watch,
+ nextTick,
+} from "vue";
+import type { CSSProperties } from "vue";
+import throttle from "lodash/throttle";
+type propsType = {
+ modelValue?: boolean;
+ list: Array<any>;
+ step?: number;
+ limitScrollNum?: number;
+ hover?: boolean;
+ direction?: string;
+ singleHeight?: number;
+ singleWidth?: number;
+ singleWaitTime?: number;
+ isRemUnit?: boolean;
+ isWatch?: boolean;
+ delay?: number;
+ ease?: any;
+ count?: number;
+ copyNum?: number;
+ wheel?: boolean;
+ singleLine?: boolean;
+};
+const props = withDefaults(defineProps<propsType>(), {
+ // 鏄惁寮�鍚嚜鍔ㄦ粴鍔�
+ modelValue: true,
+ // 鍘熷鏁版嵁鍒楄〃
+ list: () => [],
+ // 姝ヨ繘閫熷害锛宻tep 闇�鏄崟姝ュぇ灏忕殑绾︽暟
+ step: 1,
+ // 寮�鍚粴鍔ㄧ殑鏁版嵁閲�
+ limitScrollNum: 3,
+ // 鏄惁寮�鍚紶鏍囨偓鍋�
+ hover: false,
+ // 鎺у埗婊氬姩鏂瑰悜
+ direction: "up",
+ // 鍗曟杩愬姩鍋滄鐨勯珮搴�
+ singleHeight: 0,
+ // 鍗曟杩愬姩鍋滄鐨勫搴�
+ singleWidth: 0,
+ // 鍗曟鍋滄绛夊緟鏃堕棿 (榛樿鍊� 1000ms)
+ singleWaitTime: 1000,
+ // 鏄惁寮�鍚� rem 搴﹂噺
+ isRemUnit: false,
+ // 寮�鍚暟鎹洿鏂扮洃鍚�
+ isWatch: true,
+ // 鍔ㄧ敾鏃堕棿
+ delay: 0,
+ // 鍔ㄧ敾鏂瑰紡
+ ease: "ease-in",
+ // 鍔ㄧ敾寰幆娆℃暟锛�-1 琛ㄧず涓�鐩村姩鐢�
+ count: -1,
+ // 鎷疯礉鍑犱唤婊氬姩鍒楄〃
+ copyNum: 1,
+ // 寮�鍚紶鏍囨偓鍋滄椂鏀寔婊氳疆婊氬姩
+ wheel: false,
+ // 鍚敤鍗曡婊氬姩
+ singleLine: false,
+});
+interface Emits {
+ (event: "count", _count: number): void;
+ (event: "stop", _count: number): void;
+}
+const emit = defineEmits<Emits>();
+const scrollRef = ref(null);
+const slotListRef = ref<HTMLDivElement | null>(null);
+const realBoxRef = ref<HTMLDivElement | null>(null);
+const reqFrame = ref<number | null>(null);
+const singleWaitTimeout = ref<TimeProp | null>(null);
+const realBoxWidth = ref(0);
+const realBoxHeight = ref(0);
+const xPos = ref(0);
+const yPos = ref(0);
+const isHover = ref(false);
+const _count = ref(0);
+const isScroll = computed(() =>
+ props.list ? props.list.length >= props.limitScrollNum : false
+);
+const realBoxStyle = computed(() => {
+ return {
+ width: realBoxWidth.value ? `${realBoxWidth.value}px` : "auto",
+ transform: `translate(${xPos.value}px,${yPos.value}px)`,
+ transition: `all ${
+ typeof props.ease === "string"
+ ? props.ease
+ : "cubic-bezier(" +
+ props.ease.x1 +
+ "," +
+ props.ease.y1 +
+ "," +
+ props.ease.x2 +
+ "," +
+ props.ease.y2 +
+ ")"
+ } ${props.delay}ms`,
+ overflow: "hidden",
+ display: props.singleLine ? "flex" : "block",
+ };
+});
+const isHorizontal = computed(
+ () => props.direction == "left" || props.direction == "right"
+);
+
+function dataWarm(list: any) {
+ if (list && typeof list !== "boolean" && list.length > 100) {
+ console.warn(
+ `鏁版嵁杈惧埌浜�${list.length}鏉℃湁鐐瑰鍝,鍙兘浼氶�犳垚閮ㄥ垎鑰佹棫娴忚鍣ㄥ崱椤裤�俙
+ );
+ }
+}
+const floatStyle = computed<CSSProperties>(() => {
+ return isHorizontal.value
+ ? {
+ float: "left",
+ overflow: "hidden",
+ display: props.singleLine ? "flex" : "block",
+ flexShrink: props.singleLine ? 0 : 1,
+ }
+ : { overflow: "hidden" };
+});
+const baseFontSize = computed(() => {
+ return props.isRemUnit
+ ? parseInt(
+ globalThis.window.getComputedStyle(
+ globalThis.document.documentElement,
+ null
+ ).fontSize
+ )
+ : 1;
+});
+const realSingleStopWidth = computed(
+ () => props.singleWidth * baseFontSize.value
+);
+
+const realSingleStopHeight = computed(
+ () => props.singleHeight * baseFontSize.value
+);
+
+const step = computed(() => {
+ let singleStep: number;
+ let _step = props.step;
+ if (isHorizontal.value) {
+ singleStep = realSingleStopWidth.value;
+ } else {
+ singleStep = realSingleStopHeight.value;
+ }
+ if (singleStep > 0 && singleStep % _step > 0) {
+ console.error(
+ "濡傛灉璁剧疆浜嗗崟姝ユ粴鍔紝step 闇�鏄崟姝ュぇ灏忕殑绾︽暟锛屽惁鍒欐棤娉曚繚璇佸崟姝ユ粴鍔ㄧ粨鏉熺殑浣嶇疆鏄惁鍑嗙‘銆倊~~~~"
+ );
+ }
+ return _step;
+});
+
+const cancle = () => {
+ cancelAnimationFrame(reqFrame.value as number);
+ reqFrame.value = null;
+};
+const animation = (
+ _direction: "up" | "down" | "left" | "right",
+ _step: number,
+ isWheel?: boolean
+) => {
+ // console.log("animation",_direction,_step,isWheel);
+ reqFrame.value = requestAnimationFrame(function () {
+ const h = realBoxHeight.value / 2;
+ const w = realBoxWidth.value / 2;
+ if (_direction === "up") {
+ if (Math.abs(yPos.value) >= h) {
+ yPos.value = 0;
+ _count.value += 1;
+ emit("count", _count.value);
+ }
+ yPos.value -= _step;
+ } else if (_direction === "down") {
+ if (yPos.value >= 0) {
+ yPos.value = h * -1;
+ _count.value += 1;
+ emit("count", _count.value);
+ }
+ yPos.value += _step;
+ } else if (_direction === "left") {
+ if (Math.abs(xPos.value) >= w) {
+ xPos.value = 0;
+ _count.value += 1;
+ emit("count", _count.value);
+ }
+ xPos.value -= _step;
+ } else if (_direction === "right") {
+ if (xPos.value >= 0) {
+ xPos.value = w * -1;
+ _count.value += 1;
+ emit("count", _count.value);
+ }
+ xPos.value += _step;
+ }
+ if (isWheel) {
+ return;
+ }
+ let { singleWaitTime } = props;
+ if (singleWaitTimeout.value) {
+ clearTimeout(singleWaitTimeout.value);
+ }
+ if (!!realSingleStopHeight.value) {
+ if (Math.abs(yPos.value) % realSingleStopHeight.value < _step) {
+ singleWaitTimeout.value = setTimeout(() => {
+ move();
+ }, singleWaitTime);
+ } else {
+ move();
+ }
+ } else if (!!realSingleStopWidth.value) {
+ if (Math.abs(xPos.value) % realSingleStopWidth.value < _step) {
+ singleWaitTimeout.value = setTimeout(() => {
+ move();
+ }, singleWaitTime);
+ } else {
+ move();
+ }
+ } else {
+ move();
+ }
+ });
+};
+const move = () => {
+ cancle();
+ if (isHover.value || !isScroll.value || _count.value === props.count) {
+ emit("stop", _count.value);
+ _count.value = 0;
+ return;
+ }
+ animation(
+ props.direction as "up" | "down" | "left" | "right",
+ step.value,
+ false
+ );
+};
+const initMove = () => {
+ dataWarm(props.list);
+ if (isHorizontal.value) {
+ let slotListWidth = (slotListRef.value as HTMLDivElement).offsetWidth;
+ slotListWidth = slotListWidth * 2 + 1;
+ realBoxWidth.value = slotListWidth;
+ }
+ if (isScroll.value) {
+ realBoxHeight.value = (realBoxRef.value as HTMLDivElement).offsetHeight;
+ if (props.modelValue) {
+ move();
+ }
+ } else {
+ cancle();
+ yPos.value = xPos.value = 0;
+ }
+ // console.log("initMove","isHorizontal",isHorizontal.value,"isScroll",isScroll.value,realBoxRef.value?.offsetHeight);
+};
+const startMove = () => {
+ isHover.value = false;
+ move();
+};
+
+const stopMove = () => {
+ isHover.value = true;
+ if (singleWaitTimeout.value) {
+ clearTimeout(singleWaitTimeout.value);
+ }
+ cancle();
+};
+
+const hoverStop = computed(
+ () => props.hover && props.modelValue && isScroll.value
+);
+const throttleFunc = throttle((e: WheelEvent) => {
+ cancle();
+ const singleHeight = !!realSingleStopHeight.value
+ ? realSingleStopHeight.value
+ : 15;
+ if (e.deltaY < 0) {
+ animation("down", singleHeight, true);
+ }
+ if (e.deltaY > 0) {
+ animation("up", singleHeight, true);
+ }
+}, 30);
+
+const onWheel = (e: WheelEvent) => {
+ throttleFunc(e);
+};
+const reset = () => {
+ cancle();
+ isHover.value = false;
+ initMove();
+};
+const Reset = () => {
+ reset();
+};
+defineExpose({
+ Reset,
+});
+
+watch(
+ () => props.list,
+ () => {
+ if (props.isWatch) {
+ nextTick(() => {
+ reset();
+ });
+ }
+ },
+ {
+ deep: true,
+ }
+);
+
+watch(
+ () => props.modelValue,
+ (newValue) => {
+ if (newValue) {
+ startMove();
+ } else {
+ stopMove();
+ }
+ }
+);
+
+watch(
+ () => props.count,
+ (newValue) => {
+ if (newValue !== 0) {
+ startMove();
+ }
+ }
+);
+
+onBeforeMount(() => {
+ cancle();
+ clearTimeout(singleWaitTimeout.value as unknown as number);
+});
+
+onMounted(() => {
+ if (isScroll.value) {
+ initMove();
+ }
+});
+</script>
+
+<template>
+ <div
+ v-if="props.wheel && props.hover"
+ ref="realBoxRef"
+ :style="realBoxStyle"
+ @mouseenter="
+ () => {
+ hoverStop && stopMove();
+ }
+ "
+ @mouseleave="
+ () => {
+ hoverStop && startMove();
+ }
+ "
+ @wheel="
+ (e) => {
+ hoverStop && onWheel(e);
+ }
+ "
+ >
+ <div ref="slotListRef" :style="floatStyle">
+ <slot></slot>
+ </div>
+ <div :style="floatStyle">
+ <slot></slot>
+ </div>
+ </div>
+
+ <div
+ v-else
+ :style="realBoxStyle"
+ ref="realBoxRef"
+ @mouseenter="
+ () => {
+ hoverStop && stopMove();
+ }
+ "
+ @mouseleave="
+ () => {
+ hoverStop && startMove();
+ }
+ "
+ >
+ <div ref="slotListRef" :style="floatStyle">
+ <slot></slot>
+ </div>
+ <div :style="floatStyle">
+ <slot></slot>
+ </div>
+ </div>
+</template>
+
+<style scoped lang="scss"></style>
diff --git a/src/mock/mock-index.ts b/src/mock/mock-index.ts
index 72f33fb..4119b12 100644
--- a/src/mock/mock-index.ts
+++ b/src/mock/mock-index.ts
@@ -57,6 +57,31 @@
return a
}
},
+ //宸︿笅
+ {
+ url: "/bigscreen/leftBottom",
+ type: "get",
+ response: () => {
+ const a = Mock.mock({
+ success: true,
+ data: {
+ "list|20": [
+ {
+ provinceName: "@province()",
+ cityName: '@city()',
+ countyName: "@county()",
+ createTime: "@datetime('yyyy-MM-dd HH:mm:ss')",
+ deviceId: "6c512d754bbcd6d7cd86abce0e0cac58",
+ "gatewayno|+1": 10000,
+ "onlineState|1": [0, 1],
+
+ }
+ ]
+ }
+ })
+ return a
+ }
+ },
//鍙充笂
{
url: "/bigscreen/alarmNum",
@@ -82,23 +107,51 @@
url: "/bigscreen/ranking",
type: "get",
response: () => {
- let num =Mock.mock({"list|80":[{ value:"@integer(50,1000)",name:"@city()"}]}).list
+ let num = Mock.mock({ "list|80": [{ value: "@integer(50,1000)", name: "@city()" }] }).list
// console.log("ranking",num);
- let newNum:any =[],numObj:any ={}
- num.map((item:any )=>{
- if(!numObj[item.name] && newNum.length<8){
- numObj[item.name] =true
+ let newNum: any = [], numObj: any = {}
+ num.map((item: any) => {
+ if (!numObj[item.name] && newNum.length < 8) {
+ numObj[item.name] = true
newNum.push(item)
}
- })
- let arr = newNum.sort((a:any ,b:any )=>{
- return b.value-a.value
- })
- let a ={
- success:true,
- data:arr
- }
- return a
+ })
+ let arr = newNum.sort((a: any, b: any) => {
+ return b.value - a.value
+ })
+ let a = {
+ success: true,
+ data: arr
+ }
+ return a
+ }
+ },
+ //鍙充笅
+ {
+ url: "/bigscreen/rightBottom",
+ type: "get",
+ response: () => {
+ const a = Mock.mock({
+ success: true,
+ data: {
+ "list|40": [{
+ alertdetail: "@csentence(5,10)",
+ "alertname|1": ["姘存蹈鍛婅", "鍚勭鎶ヨ"],
+ alertvalue: "@float(60, 200)",
+ createtime: "2022-04-19 08:38:33",
+ deviceid: null,
+ "gatewayno|+1": 10000,
+ phase: "A1",
+ sbInfo: "@csentence(10,18)",
+ "terminalno|+1": 100,
+ provinceName: "@province()",
+ cityName: '@city()',
+ countyName: "@county()",
+ }],
+
+ }
+ })
+ return a
}
},
//瀹夎璁″垝
diff --git a/src/stores/setting/setting.ts b/src/stores/setting/setting.ts
index fc8b59a..090aa01 100644
--- a/src/stores/setting/setting.ts
+++ b/src/stores/setting/setting.ts
@@ -1,28 +1,51 @@
-import { ref, computed } from 'vue'
+import { ref, computed, reactive } from 'vue'
import { defineStore } from 'pinia'
// import { storeToRefs } from 'pinia';
export const useSettingStore = defineStore('setting', () => {
const settingShow = ref(false);//璁剧疆寮圭獥鏄鹃殣
const isScale = ref(false);//鏄惁杩涜鍏ㄥ眬閫傞厤
-
- const setSettingShow = (flag:boolean)=>{
- settingShow.value=flag
+ const indexConfig = ref({
+ leftBottomSwiper: true,//宸﹁疆鎾�
+ rightBottomSwiper: true,//鍙充笅杞挱
+ })
+ const defaultOption = ref({
+ step: 4, // 鏁板�艰秺澶ч�熷害婊氬姩瓒婂揩
+ hover: true, // 鏄惁寮�鍚紶鏍囨偓鍋渟top
+ wheel: false,//鍦ㄥ紑鍚紶鏍囨偓鍋滅殑鎯呭喌涓嬫槸鍚﹀紑鍚粴杞粴鍔紝榛樿涓嶅紑鍚�
+ openWatch: true, // 寮�鍚暟鎹疄鏃剁洃鎺у埛鏂癲om
+ direction: 1, // 0鍚戜笅 1鍚戜笂 2鍚戝乏 3鍚戝彸
+ limitScrollNum: 4, // 寮�濮嬫棤缂濇粴鍔ㄧ殑鏁版嵁閲� this.dataList.length
+ singleHeight: 0, // 鍗曟杩愬姩鍋滄鐨勯珮搴�(榛樿鍊�0鏄棤缂濅笉鍋滄鐨勬粴鍔�) direction => 0/1
+ singleWidth: 0, // 鍗曟杩愬姩鍋滄鐨勫搴�(榛樿鍊�0鏄棤缂濅笉鍋滄鐨勬粴鍔�) direction => 2/3
+ singleWaitTime: 3000 // 鍗曟杩愬姩鍋滄鐨勬椂闂�(榛樿鍊�1000ms)
+ })
+ const setSettingShow = (flag: boolean) => {
+ settingShow.value = flag
}
- const setIsScale = (flag:boolean)=>{
- isScale.value=flag
+ const setIsScale = (flag: boolean) => {
+ isScale.value = flag
setSettingData()
}
- const initSetting=()=>{
- let settingData:any = localStorage.getItem('loftv-settingData')
- if(settingData){
- settingData=JSON.parse(settingData)
- setIsScale(settingData.isScale)
+ const setIndexConfig = (Config: any) => {
+ indexConfig.value = Config
+ localStorage.setItem('loftv-indexConfig', JSON.stringify(indexConfig.value))
+ }
+ const initSetting = () => {
+ let settingData: any = localStorage.getItem('loftv-settingData')
+ if (settingData) {
+ settingData = JSON.parse(settingData)
+ setIsScale(settingData.isScale)
+ }
+ let settingIndexConfig: any = localStorage.getItem('loftv-indexConfig')
+ if (settingIndexConfig) {
+ settingIndexConfig = JSON.parse(settingIndexConfig)
+ setIndexConfig(settingIndexConfig)
}
}
- const setSettingData=()=>{
- localStorage.setItem('loftv-settingData',JSON.stringify({
- isScale:isScale.value
+ const setSettingData = () => {
+ localStorage.setItem('loftv-settingData', JSON.stringify({
+ isScale: isScale.value
}))
}
- return { settingShow, setSettingShow,isScale ,setIsScale,initSetting,setSettingData}
+ return { settingShow, setSettingShow, isScale, setIsScale, initSetting, setSettingData, defaultOption, indexConfig, setIndexConfig }
})
diff --git a/src/views/index/index.vue b/src/views/index/index.vue
index 1fec044..defb1fa 100644
--- a/src/views/index/index.vue
+++ b/src/views/index/index.vue
@@ -2,6 +2,7 @@
import ItemWrap from "@/components/item-wrap";
import LeftTop from "./left-top.vue";
import LeftCenter from "./left-center.vue";
+import LeftBottom from "./left-bottom.vue";
import CenterMap from "./center-map.vue";
import CenterBottom from "./center-bottom.vue";
import RightTop from "./right-top.vue";
@@ -32,7 +33,7 @@
title="璁惧鎻愰啋"
style="padding: 0 10px 16px 10px"
>
- <!-- <LeftBottom /> -->
+ <LeftBottom />
</ItemWrap>
</div>
<div class="contetn_center">
diff --git a/src/views/index/left-bottom.vue b/src/views/index/left-bottom.vue
new file mode 100644
index 0000000..b11f10a
--- /dev/null
+++ b/src/views/index/left-bottom.vue
@@ -0,0 +1,228 @@
+<script setup lang="ts">
+import { currentGET } from "@/api";
+import SeamlessScroll from "@/components/seamless-scroll";
+import { computed, onMounted, reactive } from "vue";
+import { useSettingStore } from "@/stores";
+import { storeToRefs } from "pinia";
+import EmptyCom from "@/components/empty-com"
+const settingStore = useSettingStore();
+const { defaultOption,indexConfig } = storeToRefs(settingStore);
+const state = reactive<any>({
+ list: [],
+ defaultOption: {
+ ...defaultOption.value,
+ singleHeight: 256,
+ limitScrollNum: 4,
+ },
+ scroll: true,
+});
+
+const getData = () => {
+ currentGET("leftBottom", { limitNum: 20 }).then((res) => {
+ console.log("璁惧鎻愰啋", res);
+ if (res.success) {
+ state.list = res.data.list;
+ } else {
+ window.$message({
+ text: res.msg,
+ type: "warning",
+ });
+ }
+ });
+};
+const addressHandle = (item: any) => {
+ let name = item.provinceName;
+ if (item.cityName) {
+ name += "/" + item.cityName;
+ if (item.countyName) {
+ name += "/" + item.countyName;
+ }
+ }
+ return name;
+};
+const comName = computed(()=>{
+ if(indexConfig.value.leftBottomSwiper){
+ return SeamlessScroll
+ }else{
+ return EmptyCom
+ }
+})
+onMounted(() => {
+ getData();
+});
+</script>
+
+<template>
+ <div class="left_boottom_wrap beautify-scroll-def" :class="{ 'overflow-y-auto': !indexConfig.leftBottomSwiper }">
+ <component
+ :is="comName"
+ :list="state.list"
+ v-model="state.scroll"
+ :singleHeight="state.defaultOption.singleHeight"
+ :step="state.defaultOption.step"
+ :limitScrollNum="state.defaultOption.limitScrollNum"
+ :hover="state.defaultOption.hover"
+ :singleWaitTime="state.defaultOption.singleWaitTime"
+ :wheel="state.defaultOption.wheel"
+ >
+ <ul class="left_boottom">
+ <li class="left_boottom_item" v-for="(item, i) in state.list" :key="i">
+ <span class="orderNum doudong">{{ i + 1 }}</span>
+ <div class="inner_right">
+ <div class="dibu"></div>
+ <div class="flex">
+ <div class="info">
+ <span class="labels">璁惧ID锛�</span>
+ <span class="text-content zhuyao doudong wangguan">
+ {{ item.gatewayno }}</span
+ >
+ </div>
+ <div class="info">
+ <span class="labels">鏃堕棿锛�</span>
+ <span class="text-content" style="font-size: 12px">
+ {{ item.createTime }}</span
+ >
+ </div>
+ </div>
+
+ <span
+ class="types doudong"
+ :class="{
+ typeRed: item.onlineState == 0,
+ typeGreen: item.onlineState == 1,
+ }"
+ >{{ item.onlineState == 1 ? "涓婄嚎" : "涓嬬嚎" }}</span
+ >
+
+ <div class="info addresswrap">
+ <span class="labels">鍦板潃锛�</span>
+ <span class="text-content ciyao" style="font-size: 12px">
+ {{ addressHandle(item) }}</span
+ >
+ </div>
+ </div>
+ </li>
+ </ul>
+ </component>
+ </div>
+</template>
+
+<style scoped lang="scss">
+.left_boottom_wrap {
+ overflow: hidden;
+ width: 100%;
+ height: 100%;
+}
+
+.doudong {
+ overflow: hidden;
+ backface-visibility: hidden;
+}
+
+.overflow-y-auto {
+ overflow-y: auto;
+}
+
+.left_boottom {
+ width: 100%;
+ height: 100%;
+
+ .left_boottom_item {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ padding: 8px;
+ font-size: 14px;
+ margin: 10px 0;
+ .orderNum {
+ margin: 0 16px 0 -20px;
+ }
+
+ .info {
+ margin-right: 10px;
+ display: flex;
+ align-items: center;
+ color: #fff;
+
+ .labels {
+ flex-shrink: 0;
+ font-size: 12px;
+ color: rgba(255, 255, 255, 0.6);
+ }
+
+ .zhuyao {
+ color: $primary-color;
+ font-size: 15px;
+ }
+
+ .ciyao {
+ color: rgba(255, 255, 255, 0.8);
+ }
+
+ .warning {
+ color: #e6a23c;
+ font-size: 15px;
+ }
+ }
+
+ .inner_right {
+ position: relative;
+ height: 100%;
+ width: 380px;
+ flex-shrink: 0;
+ line-height: 1;
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ flex-wrap: wrap;
+ .dibu {
+ position: absolute;
+ height: 2px;
+ width: 104%;
+ background-image: url("@/assets/img/zuo_xuxian.png");
+ bottom: -10px;
+ left: -2%;
+ background-size: cover;
+ }
+ .addresswrap {
+ width: 100%;
+ display: flex;
+ margin-top: 8px;
+ }
+ }
+
+ .wangguan {
+ color: #1890ff;
+ font-weight: 900;
+ font-size: 15px;
+ width: 80px;
+ flex-shrink: 0;
+ }
+
+ .time {
+ font-size: 12px;
+ // color: rgba(211, 210, 210,.8);
+ color: #fff;
+ }
+
+ .address {
+ font-size: 12px;
+ cursor: pointer;
+ // @include text-overflow(1);
+ }
+
+ .types {
+ width: 30px;
+ flex-shrink: 0;
+ }
+
+ .typeRed {
+ color: #fc1a1a;
+ }
+
+ .typeGreen {
+ color: #29fc29;
+ }
+ }
+}
+</style>
diff --git a/src/views/index/right-bottom.vue b/src/views/index/right-bottom.vue
index 7df5872..751cbd6 100644
--- a/src/views/index/right-bottom.vue
+++ b/src/views/index/right-bottom.vue
@@ -1,13 +1,198 @@
-<script setup lang='ts'>
+<script setup lang="ts">
+import { currentGET } from "@/api";
+import SeamlessScroll from "@/components/seamless-scroll";
+import { computed, onMounted, reactive } from "vue";
+import { useSettingStore } from "@/stores";
+import { storeToRefs } from "pinia";
+import EmptyCom from "@/components/empty-com";
+const settingStore = useSettingStore();
+const { defaultOption, indexConfig } = storeToRefs(settingStore);
+const state = reactive<any>({
+ list: [],
+ defaultOption: {
+ ...defaultOption.value,
+ singleHeight: 252,
+ limitScrollNum: 3,
+ // step:3
+ },
+ scroll: true,
+});
+
+const getData = () => {
+ currentGET("rightBottom", { limitNum: 20 }).then((res) => {
+ console.log("鍙充笅", res);
+ if (res.success) {
+ state.list = res.data.list;
+ } else {
+ window.$message({
+ text: res.msg,
+ type: "warning",
+ });
+ }
+ });
+};
+
+const comName = computed(() => {
+ if (indexConfig.value.rightBottomSwiper) {
+ return SeamlessScroll;
+ } else {
+ return EmptyCom;
+ }
+});
+function montionFilter (val:any) {
+ // console.log(val);
+ return val ? Number(val).toFixed(2) : '--'
+}
+const handleAddress=(item:any)=>{
+ return `${ item.provinceName }/${item.cityName }/${item.countyName}`
+}
+onMounted(() => {
+ getData();
+});
</script>
<template>
- <div class=''>
+ <div
+ class="right_bottom_wrap beautify-scroll-def"
+ :class="{ 'overflow-y-auto': !indexConfig.rightBottomSwiper }"
+ >
+ <component
+ :is="comName"
+ :list="state.list"
+ v-model="state.scroll"
+ :singleHeight="state.defaultOption.singleHeight"
+ :step="state.defaultOption.step"
+ :limitScrollNum="state.defaultOption.limitScrollNum"
+ :hover="state.defaultOption.hover"
+ :singleWaitTime="state.defaultOption.singleWaitTime"
+ :wheel="state.defaultOption.wheel"
+ >
+ <ul class="right_bottom">
+ <li class="right_center_item" v-for="(item, i) in state.list" :key="i">
+ <span class="orderNum">{{ i + 1 }}</span>
+ <div class="inner_right">
+ <div class="dibu"></div>
+ <div class="flex">
+ <div class="info">
+ <span class="labels">璁惧ID锛�</span>
+ <span class="text-content zhuyao"> {{ item.gatewayno }}</span>
+ </div>
+ <div class="info">
+ <span class="labels">鍨嬪彿锛�</span>
+ <span class="text-content"> {{ item.terminalno }}</span>
+ </div>
+ <div class="info">
+ <span class="labels">鍛婅鍊硷細</span>
+ <span class="text-content warning">
+ {{ montionFilter(item.alertvalue) }}</span
+ >
+ </div>
+ </div>
+ <div class="flex">
+ <div class="info">
+ <span class="labels shrink-0"> 鍦板潃锛�</span>
+ <span class=" ciyao truncate" style="font-size: 12px;width: 220px;" :title="handleAddress(item)">
+ {{ handleAddress(item)}}</span
+ >
+ </div>
+ <div class="info time shrink-0">
+ <span class="labels">鏃堕棿锛�</span>
+ <span class="text-content" style="font-size: 12px">
+ {{ item.createtime }}</span
+ >
+ </div>
+ </div>
+ <div class="flex">
+ <div class="info">
+ <span class="labels">鎶ヨ鍐呭锛�</span>
+ <span
+ class="text-content ciyao"
+ :class="{ warning: item.alertdetail }"
+ >
+ {{ item.alertdetail || "鏃�" }}</span
+ >
+ </div>
+ </div>
+ </div>
+ </li>
+ </ul>
+ </component>
</div>
</template>
-<style scoped lang='scss'>
+<style scoped lang="scss">
+.right_bottom {
+ width: 100%;
+ height: 100%;
-</style>
\ No newline at end of file
+ .right_center_item {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ height: auto;
+ padding: 10px;
+ font-size: 14px;
+ color: #fff;
+
+ .orderNum {
+ margin: 0 20px 0 -20px;
+ }
+
+ .inner_right {
+ position: relative;
+ height: 100%;
+ width: 400px;
+ flex-shrink: 0;
+ line-height: 1.5;
+
+ .dibu {
+ position: absolute;
+ height: 2px;
+ width: 104%;
+ background-image: url("@/assets/img/zuo_xuxian.png");
+ bottom: -12px;
+ left: -2%;
+ background-size: cover;
+ }
+ }
+
+ .info {
+ margin-right: 10px;
+ display: flex;
+ align-items: center;
+
+ .labels {
+ flex-shrink: 0;
+ font-size: 12px;
+ color: rgba(255, 255, 255, 0.6);
+ }
+
+ .zhuyao {
+ color: $primary-color;
+ font-size: 15px;
+ }
+
+ .ciyao {
+ color: rgba(255, 255, 255, 0.8);
+ }
+
+ .warning {
+ color: #e6a23c;
+ font-size: 15px;
+ }
+ }
+ }
+}
+
+.right_bottom_wrap {
+ overflow: hidden;
+ width: 100%;
+ height: 252px;
+}
+
+.overflow-y-auto {
+ overflow-y: auto;
+}
+</style>
diff --git a/src/views/setting.vue b/src/views/setting.vue
index 1302013..ca02c87 100644
--- a/src/views/setting.vue
+++ b/src/views/setting.vue
@@ -1,11 +1,20 @@
<script setup lang="ts">
import { useSettingStore } from "@/stores/index";
import { ref } from "vue";
+import {storeToRefs} from "pinia"
const isScaleRadio = ref(false);
+const leftBottomRadio=ref(true)
+const rightBottomRadio=ref(true)
const settingStore = useSettingStore();
+const {indexConfig}=storeToRefs(settingStore)
+
const init = () => {
settingStore.initSetting();
isScaleRadio.value = settingStore.isScale;
+
+ leftBottomRadio.value=indexConfig.value.leftBottomSwiper
+ rightBottomRadio.value=indexConfig.value.rightBottomSwiper
+
};
init();
const handleClose = () => {};
@@ -18,11 +27,16 @@
const isScaleChange = (flag: boolean) => {
settingStore.setIsScale(flag);
};
-const radiochange = (blag: boolean, type: string) => {
- console.log(blag, type);
+const radiochange = (blag: boolean) => {
settingStore.setIsScale(blag);
// this.$store.commit('setting/updateSwiper', { val, type })
};
+const indexRadioChange=(flag: boolean)=>{
+ settingStore.setIndexConfig({
+ leftBottomSwiper: leftBottomRadio.value,//宸﹁疆鎾�
+ rightBottomSwiper:rightBottomRadio.value,//鍙充笅杞挱
+ });
+}
</script>
<template>
@@ -45,6 +59,33 @@
</el-radio-group>
</div>
</div>
+ <div class="left_shu">瀹炴椂鐩戞祴</div>
+ <div class="setting_item">
+ <span class="setting_label">
+ 璁惧鎻愰啋鑷姩杞: <span class="setting_label_tip"></span>
+ </span>
+ <div class="setting_content">
+ <el-radio-group
+ v-model="leftBottomRadio"
+ @change="indexRadioChange"
+ >
+ <el-radio :label="true">鏄�</el-radio>
+ <el-radio :label="false">鍚�</el-radio>
+ </el-radio-group>
+ </div>
+ </div>
+ <div class="setting_item">
+ <span class="setting_label"> 瀹炴椂棰勮杞挱: </span>
+ <div class="setting_content">
+ <el-radio-group
+ v-model="rightBottomRadio"
+ @change="indexRadioChange"
+ >
+ <el-radio :label="true">鏄�</el-radio>
+ <el-radio :label="false">鍚�</el-radio>
+ </el-radio-group>
+ </div>
+ </div>
</template>
<!-- <template #footer>
<div style="flex: auto">
diff --git a/types/global.d.ts b/types/global.d.ts
index dbb4020..653a7de 100644
--- a/types/global.d.ts
+++ b/types/global.d.ts
@@ -1,3 +1,5 @@
interface Window {
$message: any
}
+
+type TimeProp= NodeJS.Timeout
\ No newline at end of file
--
Gitblit v1.8.0